/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "S_物体.h"

#include "core/动画/an_曲线.h"
#include "core/shader_line.h"
#include "底层绘图/底层绘图框架.h"
#include "底层绘图/intern/Vulkan/buffer/Vk缓存.h"

#include "面/Mesh.h"
#include "面/面.h"

#include "S_键值序列容器.h"
#include <matXX.h>
#include <随机数.h>
#include <线性代数/变换.h>

#include <omp.h>
#include "物体.h"



std::set<S_物体*> g物体ID;
std::set<S_骨架*> C_骨骼管理::m_骨骼容器;

static S_键值序列容器<uint32, S_物体*> g_物体容器;
static C_骨骼管理 g_骨骼容器;

static std::vector<S_Mesh*> g更新光追网格;
static uint32 g更新光追网格数量 = 0;

//static std::vector<S_物体*> g更新变换物体;
static uint32 g更新变换物体数量 = 0;

static std::set<S_物体*> g更新变换物体;
static std::set<S_物体*> g光追更新物体;


static bool g_可视[128] = {};
static bool g_帧时间改变 = false;
//float64 S_物体::g_前一帧 = 0.0;
//float64 S_物体::g_当前帧 = 0.0;

bool                     S_物体::g_更新曲线关键帧 = true;
//S_物体*                  S_物体::g_包围盒物体 = nullptr;
//S_板载缓存*              S_物体::g_变换矩阵 = nullptr;

S_板载缓存*              S_物体::g_物体属性 = nullptr;
//std::vector<S_板载缓存*> S_物体::g_物体颜色;

S_板载缓存* S_物体::g_骨骼姿态 = nullptr;

static std::vector<std::unique_ptr<C_物体缓存列队数据>> g物体列队缓存;





//void on_mesh绘制参数设置(S_物体* ob, S_Mesh* me, const S_GPU内存块索引* 物体参数[2]) {
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->MeshPropOffset = me->m_网格元素属性.m_Mem.m_偏移;
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->MatrixOffset = 物体参数[0]->m_Mem.m_偏移;
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->ColorPropOffset = 物体参数[1]->m_Mem.m_偏移;
//
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->Offset_Face_AdjacencyID = (me->m_邻接面索引)->m_Mem.m_偏移;
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->Offset_Face_Normal = (me->m_面法线)->m_Mem.m_偏移;
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->Offset_Face_Center = (me->m_面中心)->m_Mem.m_偏移;
//
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->VertexOffset = (me->m_顶点)->m_Mem.m_偏移;
//
//
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->BoneNum = (me->m_顶点骨骼属性)->m_Mem.m_大小;
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->BonesOffset = (me->m_顶点骨骼属性)->m_Mem.m_偏移;
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->BoneWeigetOffset = (me->m_骨骼权重映射)->m_Mem.m_偏移;
//
//	((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->BonePoseOffset = ob->m_骨架->m_姿态.m_Mem.m_偏移;
//}




void S_物体变换::f_set矩阵(const float32* mat) {
	m_矩阵 = *((const Mat44f*)mat);
}



void f_ob_销毁网格包(S_网格包& 网格包) {
	--(网格包.m_Mesh->m_引用计数);

	f_df_销毁常量推送(网格包.m_常量推送);
}

void on_物体变换生成(S_物体* ob, Mat44f* 矩阵, const Mat44f* 父级变换) {
	//float64 t = ob->g_当前帧 + ob->m_TimeOffset;

	vec3 loc = ob->m_变换.position;
	vec3 rot = ob->m_变换.rotation;
	vec3 scale = ob->m_变换.scale;
	vec3 loc_scale = ob->m_变换.locScale;


	if (S_物体::g_更新曲线关键帧) {
		if (ob->m_位置) {
			//loc = f_an_曲线值(ob->m_位置, t);
		}
		if (ob->m_旋转) {
			//rot = f_an_曲线值(ob->m_旋转, t);
		}
		if (ob->m_缩放) {
			//scale = f_an_曲线值(ob->m_缩放, t);
		}
		//if (ob->m_位置) {
		//	ob->m_变换.location = f_an_曲线值(ob->m_位置, t);
		//}
		//if (ob->m_旋转) {
		//	ob->m_变换.rotation = f_an_曲线值(ob->m_旋转, t);
		//}
		//if (ob->m_缩放) {
		//	ob->m_变换.scale = f_an_曲线值(ob->m_缩放, t);
		//}
	}

	switch (ob->m_父级变换关系) {
		case E_父级变换关系::e_变换关系_继承: {
			(*矩阵) = *父级变换;
			return;
		}

		default: {
			
			auto 移动 = f_mat44_构建移动矩阵(loc);
			auto 缩放 = f_mat44_构建缩放矩阵(scale);
			ob->m_旋转矩阵 = f_mat44_构建XYZ旋转矩阵(rot);

			(*矩阵) = 移动* ob->m_旋转矩阵 * (缩放) ;
			//(*矩阵) = f_mat44_构建XYZ变换矩阵({ loc, rot, scale, loc_scale });
			break;
		}
			
	}
	(*矩阵) = (*父级变换) * (*矩阵);
}

void f_mesh_构建网格属性参数(S_物体* ob, S_Mesh* me, uint32 ObType) {
	S_ObMesh mesh = {
		f_buf_getOffsetAddress(*me->m_顶点),
		f_buf_getOffsetAddress(*me->m_UV),
		f_buf_getOffsetAddress(*me->m_UV索引),
		f_buf_getOffsetAddress(*me->m_索引),
		f_buf_getOffsetAddress(*me->m_面),

		f_buf_getOffsetAddress(*me->m_自定义属性索引),
		f_buf_getOffsetAddress(*me->m_邻接面索引),
		f_buf_getOffsetAddress(*me->m_面法线),
		f_buf_getOffsetAddress(*me->m_面中心),

		//f_buf_getOffsetAddress(ob->m_自定义属性索引),

		me->m_几何属性.uvLayerAndOffset,
		me->m_几何属性.uvIndexOffset012,
		me->m_几何属性.uvIndexOffset345,
		me->m_几何属性.uvIndexOffset678,

		me->f_getBound().max - f_me_getBound(me).min,
		f_me_getBound(me).min,

		ObType,
		0,
		0,
		//ob->m_变换.location,
		me->m_包围盒->pos,
	};

	f_buf_网格引用_at(*me->m_网格属性) = mesh;
}

void f_ob_骨骼物体变换生成(S_物体* ob, Mat44f* 矩阵, const Mat44f* 父级变换) {
	
	//float64 t = ob->g_当前帧 + ob->m_TimeOffset;

	vec3 loc = ob->m_变换.position;
	if (ob->m_位置) {
		//loc = f_an_曲线值(ob->m_位置, t);
	}

	vec3 rot = ob->m_变换.rotation;
	if (ob->m_旋转) {
		//rot = f_an_曲线值(ob->m_旋转, t);
	}

	vec3 scale = ob->m_变换.scale;
	if (ob->m_缩放) {
		//scale = f_an_曲线值(ob->m_缩放, t);
	}


	float32 长度 = 0;
	vec3 偏移{};
	if (ob->m_父对象 && ((S_物体*)(ob->m_父对象))->m_Type == E_物体类型::t_骨骼) {
		S_骨骼* 父骨骼 = f_ob_from骨骼((S_物体*)(ob->m_父对象));

		长度 = 父骨骼->m_长度;
		偏移 = { 0,0,父骨骼->m_长度 };

		scale.x = scale.x;
		scale.y = scale.x;
		scale.z = scale.x;
	}
	else {
		偏移 = loc;

		scale.x = scale.x;
		scale.y = scale.x;
		scale.z = scale.x;
	}



	Mat44f mat = f_mat44_构建XYZ变换矩阵({ 偏移, rot, scale });
	if (父级变换) {
		mat = (*父级变换) * mat;
		
	}
	(*矩阵) = mat;


	if(ob->m_Type == E_物体类型::t_骨骼) {
		S_骨骼* 骨骼 = f_ob_from骨骼(ob);
		骨骼->m_变换后根坐标 = mat * vec3{ 0,0,0 };
		//骨骼->m_变换后尾坐标 = mat * vec3{ DEF_骨骼朝向 };
		骨骼->m_变换后尾坐标 = mat * (vec3{ DEF_骨骼朝向 } * 骨骼->m_长度);
	}
	//ob->m_骨架;

	return;

}


Inline void f_子物体更新(S_物体** ob, uint32 num, Mat44f* 当前矩阵ptr, Mat44f* 父级变换) {
	if (num > 2048) {
		//omp_set_num_threads(8);
#pragma omp parallel for num_threads(16)
		for (int32 i = 0; i < num; ++i) {
			ob[i]->f_Update(当前矩阵ptr, 父级变换);
		}
	}
	else {
		for (uint32 i = 0; i < num; ++i) {
			ob[i]->f_Update(当前矩阵ptr, 父级变换);
		}
	}
}




S_物体::S_物体(E_物体类型 type, uint32 id_name) : S_Object(type, id_name), m_UpdateGPU参数布局(true){
	m_UserData = nullptr;
	m_多边形 = nullptr;

	m_Data = nullptr;
	
	m_DataNum = 0;
	m_附属类型 = E_物体类型::t_空;

	m_深度偏移 = 0;


	m_网格拾取元素 = 0;
	m_实例ID = 0;
	m_变换ID = 0;
	m_TimeOffset = 0.0f;
	f_TranformInit(m_变换);
	m_全局缩放矩阵 = f_mat44_identity();
	m_旋转矩阵 = f_mat44_identity();

	m_变换矩阵 = {};
	m_实例材质ID = {};
	m_光追实例加速结构 = {};
	m_光追顶层加速结构 = {};
	m_物体属性 = {};
	
	

	m_父级变换关系	= E_父级变换关系::e_变换关系_保持偏移;
	m_颜色			= {128,128,128,255};
	m_父对象		= nullptr;
	m_独立缩放 = nullptr;
	//m_实例颜色 = {};
	
	m_骨架 = nullptr;
	m_位置 = nullptr;
	m_旋转 = nullptr;
	m_缩放 = nullptr;

	mf_更新变换 = nullptr;
	switch (type) {
		case E_物体类型::t_实例:
			m_是否实例 = true;
			mf_变换回调更新 = on_物体变换生成;
			m_自定义属性索引 = {};
			break;

		case E_物体类型::t_骨骼:
			m_是否实例 = false;
			mf_变换回调更新 = f_ob_骨骼物体变换生成;
			m_自定义属性索引 = {};
			break;
		default:
			m_是否实例 = false;
			mf_变换回调更新 = on_物体变换生成;

			auto p = &f_buf_getGlobal().g_自定义属性索引;
			m_自定义属性索引 = f_bm_alloc(f_buf_getGlobal().g_自定义属性索引, DEF_网格自定义属性槽数量 * DEF_网格自定义属性槽数量);

			break;
	}
	//m_显示 = true;
	m_根实例	= false;
	
	
	m_渲染		= true;
	m_销毁      = false;
	
	f_ob_设置反弹场景和遮罩类型(this, 0, DEF_Mask_None);


	m_视口显示模式 = E_物体视口显示::e_OVS_面 
				| E_物体视口显示::e_OVS_边 
				| E_物体视口显示::e_OVS_边框 
				| E_物体视口显示::e_OVS_点
				| E_物体视口显示::e_OVS_光照
				
				| E_物体视口显示::e_OVS_预览
				| E_物体视口显示::e_OVS_渲染
				;

	m_视口显示模式 |= E_物体视口显示::e_OVS_面		<< 16
				| E_物体视口显示::e_OVS_边		<< 16
				//| E_物体视口显示::e_OVS_边框	<< 16
				| E_物体视口显示::e_OVS_预览	<< 16
				| E_物体视口显示::e_OVS_渲染	<< 16
				;

	m_渲染模式 = E_物体视口显示::e_OVS_预览 | E_物体视口显示::e_OVS_渲染;

	
	m_isUpdateMatrix = true;
	m_isUpdate = true;
	
	m_PickIndirect = {};


	

}

S_物体::~S_物体() {
	if (m_变换矩阵.m_Buf) f_bm_erase(m_变换矩阵);
	if (m_自定义属性索引.m_Buf) f_bm_erase(m_自定义属性索引);

	for (auto& e : m_网格模型) {
		f_ob_销毁网格包(e);
	}
	m_网格模型.clear();

	for (auto& e : m_实例颜色) {
		if (e.m_Buf) f_bm_erase(e);
	}
	
	free(m_Data);
	m_Data = 0;
	m_DataNum = 0;


	if (m_多边形) {
		delete m_多边形;
	}
}


void S_物体::f_set位置(float32 x, float32 y, float32 z) {
	m_变换.position.x = x;
	m_变换.position.y = y;
	m_变换.position.z = z;

	m_isUpdate = true;
}
void S_物体::f_set旋转(float32 x, float32 y, float32 z) {
	m_变换.rotation.x = x;
	m_变换.rotation.y = y;
	m_变换.rotation.z = z;

	m_isUpdate = true;
}
void S_物体::f_set缩放(float32 x, float32 y, float32 z) {
	m_变换.scale.x = x;
	m_变换.scale.y = y;
	m_变换.scale.z = z;

	m_isUpdate = true;
}

void S_物体::f_set位置(const vec3& xyz, uint32 实例) {
	m_变换.position = xyz;
	m_isUpdate = true;
}
void S_物体::f_set旋转(const vec3& xyz, uint32 实例) {
	m_变换.rotation = xyz;
	m_isUpdate = true;
}
void S_物体::f_set缩放(const vec3& xyz, uint32 实例) {
	m_变换.scale = xyz;
	m_isUpdate = true;
}

vec3 S_物体::f_get位置() {
	if (m_位置 && g_更新曲线关键帧) {
		//float64 t = g_当前帧 + m_TimeOffset;
		//m_变换.position = f_an_曲线值(m_位置, t);
	}
	return m_变换.position; 
}
vec3 S_物体::f_get旋转() {
	if (m_旋转 && g_更新曲线关键帧) {
		//float64 t = g_当前帧 + m_TimeOffset;
		//m_变换.rotation = f_an_曲线值(m_旋转, t);
	}
	return m_变换.rotation; 
}
vec3 S_物体::f_get缩放() {
	if (m_缩放 && g_更新曲线关键帧) {
		//float64 t = g_当前帧 + m_TimeOffset;
		//m_变换.scale = f_an_曲线值(m_缩放, t);
	}
	return m_变换.scale; 
}

vec4 S_物体::f_get四元数() {
	return f_graph_欧拉角转四元数(m_变换.rotation);
}

std::vector<Mat44f> S_物体::f_get矩阵2(uint32 ID) {
	if (m_变换矩阵.m_Mem.m_数量) {
		std::vector<Mat44f> mat(m_变换矩阵.m_Mem.m_数量);
		for (uint32 i = 0; i < m_变换矩阵.m_Mem.m_数量; ++i) {
			mat[i] = f_buf_Mat44_at(m_变换矩阵, i);
		}

		/*m_变换矩阵->f_map();
		for (uint32 i = 0; i < m_变换矩阵->m_Size; ++i) {
			mat[i] = *((Mat44f*)(m_变换矩阵->m_mappedPtr));
		}
		m_变换矩阵->f_unmap();*/

		return mat;
	}
	return {};
}

//C_Mat44 S_物体::f_get矩阵() const {
//	C_Mat44 mat = C_Mat44::kIdentity;
//	*((Mat44f*)mat.columns) = f_mat44_构建XYZ变换矩阵(m_变换);
//	return mat;
//}

Mat44f S_物体::f_get矩阵2() const {
	Mat44f m = f_mat44_构建XYZ变换矩阵(m_变换);
	return m;
}

void S_物体::f_set矩阵(const Mat44f* mat) {
	f_buf_Mat44_at(((S_物体*)(m_父对象))->m_变换矩阵, m_变换ID) = *mat;
}

void S_物体::f_set矩阵(const Mat44f* mat, uint32 id) {
	f_buf_Mat44_at(((S_物体*)(m_父对象))->m_变换矩阵, id) = *mat;
}


void S_物体::f_setData(void* data, uint16 loc) {
	assert(loc < m_DataNum);
	m_Data[loc] = data;
	m_isUpdate = true;
}

void S_物体::f_setDataNum(uint16 num) {
	void** temp = m_Data;

	if (num) {
		uint16 当前数据大小 = DEF_Min(num, m_DataNum);

		m_Data = (void**)calloc(num, sizeof(void*));
		for (uint16 i = 0; i < 当前数据大小; ++i) {
			m_Data[i] = temp[i];
		}

		for (uint16 i = 当前数据大小; i < num; ++i) {
			m_Data[i] = nullptr;
		}
	}
	else {
		m_Data = nullptr;
	}


	S_管线槽*		m_多维材质槽;
	uint32			m_多维材质数量;

	if (temp) free(temp);
	m_DataNum = num;
}



std::vector<S_物体*> S_物体::f_创建实例(uint32 num) {
	uint32 offset = m_变换矩阵.m_Mem.m_数量;
	f_bm_resize(m_变换矩阵, offset + num);
	//f_gbuf_resize(m_物体网格属性, offset + num);

	for (auto& e : m_实例颜色) {
		f_bm_resize(e, offset + num);
	}

	std::vector<S_物体*> objs(num);
	for (uint16 i = 0; i < num; ++i) {
		objs[i] = new S_物体(m_Type, 0);
		objs[i]->m_实例ID = offset + i;
		objs[i]->m_是否实例 = true;
	}
	
	return objs;
}

void S_物体::f_Update(Mat44f* c, Mat44f* 父级变换) {
	uint32 num = m_子物体.size();
	auto* objs = m_子物体.data();

	uint32 变换数量 = 0;
	Mat44f* 当前矩阵ptr = c;
	if (m_变换矩阵.m_Buf && m_变换矩阵.m_Mem.m_数量) {
		当前矩阵ptr = f_buf_Mat44_ptr(m_变换矩阵);
		变换数量 = m_变换矩阵.m_Mem.m_数量;
	}

	if (g_帧时间改变) {
		//float64 t = g_当前帧 + m_TimeOffset;
		if (m_位置 || m_旋转 || m_缩放) {
			m_isUpdate = true;
		}
	}
	
	Mat44f mat;
	if (父级变换) {
		mat = *父级变换;
	}
	else {
		mat = f_mat44_identity();
	}

	if (this->m_父对象) {
		m_isUpdate |= ((S_物体*)(this->m_父对象))->m_isUpdate;
	}


	switch (m_Type) {
		case E_物体类型::t_摄像机:
		case E_物体类型::t_GL立即模式:
			return;

		case E_物体类型::t_物体包:
		case E_物体类型::t_线:
		case E_物体类型::t_实例:
		case E_物体类型::t_粒子系统:
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体: {
			
			if (m_isUpdate || (m_位置 || m_旋转 || m_缩放)) {
				
				

				if (m_根实例) {
					//mat = f_mat44_构建XYZ变换矩阵(m_父物体->m_变换);
					//父级变换 = &当前矩阵ptr[m_实例ID];
				}
				else {
					on_物体变换生成(this, &(当前矩阵ptr[m_实例ID]), &mat);

					父级变换 = &当前矩阵ptr[m_实例ID];
				}
				m_isUpdateMatrix = true;
			}

			if (m_isUpdateMatrix) {
				if (m_DataNum) {
					//S_Mesh* mesh = (S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_面]);
					S_Mesh* mesh = (S_Mesh*)(m_Data[0]);
					
					m_Bound = mesh->f_getBound();
					f_me_set包围盒(mesh, f_ob_get包围盒(当前矩阵ptr[m_实例ID], m_Bound));
					m_包围盒 = mesh->f_get包围盒();


					if (m_DataNum > E_物体网格元素类型::e_MT_框) {
						vec3 size = (m_Bound.max - m_Bound.min);

						auto& 元素绘制属性 = f_mesh_get网格元素绘制属性((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_框]));
						元素绘制属性.m_XScale = size.x;
						元素绘制属性.m_YScale = size.y;
						元素绘制属性.m_ZScale = size.z;

						元素绘制属性.m_XMove = m_Bound.min.x;
						元素绘制属性.m_YMove = m_Bound.min.y;
						元素绘制属性.m_ZMove = m_Bound.min.z;

						f_me_setBound((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_框]), m_Bound);
						f_me_set包围盒((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_框]), m_包围盒);
					}
					if (m_DataNum > E_物体网格元素类型::e_MT_边) {
						f_me_setBound((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_边]), m_Bound);
						f_me_set包围盒((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_边]), m_包围盒);
					}
					if (m_DataNum > E_物体网格元素类型::e_MT_光照) {
						f_me_setBound((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_光照]), m_Bound);
						f_me_set包围盒((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_光照]), m_包围盒);
					}
				}
				else {
					if (m_父对象) {
						vec3 最小 = 当前矩阵ptr[m_实例ID] * ((S_物体*)(m_父对象))->m_Bound.min;
						vec3 最大 = 当前矩阵ptr[m_实例ID] * ((S_物体*)(m_父对象))->m_Bound.max;

						m_包围盒.pos = 最小;
						m_包围盒.size = (最大 - 最小);
						m_包围盒.pos += m_包围盒.size * 0.5;
					}
				}
			}
		
			
			break;
		}

	
		case E_物体类型::t_骨节:
		case E_物体类型::t_骨骼: {
			if (m_isUpdate || (m_位置 || m_旋转 || m_缩放)) {
				f_ob_骨骼物体变换生成(this, &当前矩阵ptr[m_实例ID], &mat);

				if (m_DataNum) {
					vec3 minBound = { 10000000,10000000 ,10000000 }, maxBound = { -10000000,-10000000,-10000000 };
					for (uint32 i = 0; i < m_DataNum; ++i) {
						S_Mesh* mesh = (S_Mesh*)(m_Data[i]);
						minBound = vec_Min(mesh->f_getBound().min, minBound);
						maxBound = vec_Max(mesh->f_getBound().max, maxBound);
					}
					m_Bound = S_Bounding{ minBound , maxBound };
					m_包围盒 = f_ob_get包围盒(当前矩阵ptr[m_实例ID], m_Bound);
				}
			}
			if (m_根实例) {
			
			}
			else {
				父级变换 = &当前矩阵ptr[m_实例ID];
			}
			break;
		}

		case E_物体类型::t_线段:
		case E_物体类型::t_标注:
		case E_物体类型::t_骨架: {
			if (当前矩阵ptr) {
				if (m_isUpdate || (m_位置 || m_旋转 || m_缩放)) {
					mf_变换回调更新(this, &当前矩阵ptr[m_实例ID], &mat);
				}
				父级变换 = &当前矩阵ptr[m_实例ID];
			}
			break;
		}
		case E_物体类型::t_点:
		case E_物体类型::t_灯光:
		case E_物体类型::t_平行光:
		case E_物体类型::t_点光源:
		
		
		case E_物体类型::t_虚拟体: {
			if (当前矩阵ptr) {
				if (m_isUpdate || (m_位置 || m_旋转 || m_缩放)) {
					mf_变换回调更新(this, &当前矩阵ptr[m_实例ID], &mat);

					if (m_DataNum) {
						vec3 minBound = {10000000,10000000 ,10000000 }, maxBound = {-10000000,-10000000,-10000000 };
						for (uint32 i = 0; i < m_DataNum; ++i) {
							S_Mesh* mesh = (S_Mesh*)(m_Data[i]);
							minBound = vec_Min(mesh->f_getBound().min, minBound);
							maxBound = vec_Max(mesh->f_getBound().max, maxBound);
						}
						m_Bound = S_Bounding{ minBound , maxBound };
						m_包围盒 = f_ob_get包围盒(当前矩阵ptr[m_实例ID], m_Bound);

						//f_me_setBound((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_光照]), m_Bound);
						//f_me_set包围盒((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_光照]), m_包围盒);
						//vec3 size = (maxBound - minBound);
					}
				}
				父级变换 = &当前矩阵ptr[m_实例ID];
			}
			break;
		}

		case E_物体类型::t_空间曲线: {
			if (m_isUpdate || (m_位置 || m_旋转 || m_缩放)) {
				on_物体变换生成(this, &(当前矩阵ptr[m_实例ID]), &mat);
				m_isUpdateMatrix = true;

				S_Mesh* mesh = (S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_面]);

				m_Bound = mesh->f_getBound();
				f_me_set包围盒(mesh, f_ob_get包围盒(当前矩阵ptr[m_实例ID], m_Bound));
				m_包围盒 = mesh->f_get包围盒();


				auto& 元素绘制属性 = f_mesh_get网格元素绘制属性((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_框]));
				vec3 size = (m_Bound.max - m_Bound.min);
				元素绘制属性.m_XScale = size.x;
				元素绘制属性.m_YScale = size.y;
				元素绘制属性.m_ZScale = size.z;

				元素绘制属性.m_XMove = m_Bound.min.x;
				元素绘制属性.m_YMove = m_Bound.min.y;
				元素绘制属性.m_ZMove = m_Bound.min.z;

				f_me_setBound((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_框]), m_Bound);
				f_me_set包围盒((S_Mesh*)(m_Data[E_物体网格元素类型::e_MT_框]), m_包围盒);
			}
			break;
		}
		
		case E_物体类型::t_聚光灯:
		case E_物体类型::t_区域光:
		case E_物体类型::t_区域光_方形:
		case E_物体类型::t_区域光_圆形:
		//case E_物体类型::t_聚光灯:
		//case E_物体类型::t_区域光:
		//case E_物体类型::t_平行光:
		//case E_物体类型::t_点光源: 
		{
			if (m_isUpdate || (m_位置 || m_旋转 || m_缩放)) {
				mf_变换回调更新(this, &当前矩阵ptr[m_实例ID], &mat);
			}
			m_包围盒.pos = 当前矩阵ptr[m_实例ID] * vec3{0,0,0};
			m_包围盒.size = f_mat44_to_33(当前矩阵ptr[m_实例ID]) * m_变换.scale;
			父级变换 = &当前矩阵ptr[m_实例ID];

			break;
		}
		

	
		case E_物体类型::t_包: {
			for (uint32 j=0; j < m_DataNum; ++j) {
				S_Mesh* mesh = (S_Mesh*)(m_Data[j]);
				if (mesh->m_间接 && mesh->m_间接->m_Mem.m_数量) {
					auto indirect_ptr = f_buf_Indirect_ptr(*mesh->m_间接);
					for (uint32 i = 0; i < mesh->m_间接->m_Mem.m_数量; ++i) {
						//indirect_ptr[i].firstInstance = m_变换矩阵.m_Mem.m_偏移 + i;
						indirect_ptr[i].firstInstance = i;
						//indirect_ptr[i].firstInstance = 0;
					}
				}
			}

			if (m_isUpdate || (m_位置 || m_旋转 || m_缩放)) {
				on_物体变换生成(this, &当前矩阵ptr[m_实例ID], &mat);
				m_isUpdateMatrix = true;
			}
			父级变换 = &当前矩阵ptr[m_实例ID];
			break;
		}
		default:
			break;
	}

	
	if (m_根实例) {
		f_子物体更新((S_物体**)objs, num, 当前矩阵ptr, 父级变换);
	}
	else {
		f_子物体更新((S_物体**)objs, num, 当前矩阵ptr, 父级变换);
	}
	
	

	switch (m_Type) {
		case E_物体类型::t_粒子系统:
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体: {
			S_Mesh* me = f_ob_getMesh(this, E_物体网格元素类型::e_MT_光照);

			if (me && me->m_底层光追加速结构->m_Buf) {
				
				if (me->m_更新光追加速结构) {
					if (g更新光追网格数量 >= g更新光追网格.size()) {
						g更新光追网格.emplace_back(me);
					}
					else {
						g更新光追网格[g更新光追网格数量] = me;
					}
					++g更新光追网格数量;
				}

				if (m_isUpdate) {
					//if (m_isUpdate && me->m_索引->m_Mem.m_数量) {
					//if (g更新变换物体数量 >= g更新变换物体.size()) {
					//	g更新变换物体.emplace_back(this);
					//}
					//else {
					//	g更新变换物体[g更新变换物体数量] = this;
					//}
					//++g更新变换物体数量;
					g更新变换物体.insert(this);
				}
			}
			
			break;
		}
		case E_物体类型::t_骨架: {
			//auto* ob = (S_物体*)(objs[i]);
			this->f_Update(当前矩阵ptr, 父级变换);

			auto* 骨架 = f_ob_from骨架(this);
			if (骨架 && 骨架->m_解算约束) {

				if (骨架->m_IK数量) {
					f_ob_解算骨骼IK(this);
				}

				for (uint32 i = 0; i < num; ++i) {
					if (this->m_Type == E_物体类型::t_骨节) {
						this->m_isUpdate = true;
					}
				}

				if (num > 2) {
					f_ob_从骨骼更新骨节(this);
					f_ob_构建骨骼变换GPU数据(骨架, this, 当前矩阵ptr[m_实例ID]);
				}
			}
			break;
		}
	}

	m_isUpdate = false;
	m_isUpdateMatrix = false;
}


void S_物体::f_绘制(S_渲染参数& 参数) {
	S_渲染参数 渲染参数 = 参数;

	if(!m_DataNum || !m_显示 || m_是否实例) goto To_跳过绘制;
	
	switch (m_Type) {
		case E_物体类型::t_GL立即模式:
		case E_物体类型::t_实例:
		case E_物体类型::t_摄像机:
		case E_物体类型::t_区域光:
			break;
		default: {
			for (uint8 绘制元素 = 0; 绘制元素 < m_DataNum; ++绘制元素) {
				//if (m_是否实例) continue;
				S_Mesh* me = ((S_Mesh*)(m_Data[绘制元素]));
				
				if ((m_视口显示模式 & 1 << 绘制元素) && (m_视口显示模式 & 65536 << 绘制元素) && me->m_显示) {
					f_ob_绘制元素(this, me, 绘制元素, 渲染参数, false);
				}
			}
			break;
		}
	}
	//}

	To_跳过绘制:
	//return;
	uint32 num = m_子物体.size();
	auto* objs = m_子物体.data();
	for (uint32 i = 0; i < num; ++i)
		if( ((S_物体*)(objs[i]))->m_是否实例 == false) ((S_物体*)(objs[i]))->f_绘制(参数);

}

void S_物体::f_打开可视通道(uint8 通道) {
	if (m_是否实例 && m_父对象) {
		((S_物体*)(m_父对象))->f_打开可视通道(通道);
	}
	else {
		switch (m_Type) {
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体: {
			((S_Mesh*)(m_Data[通道]))->m_显示 = true;
			break;
		}
		}
	}
	
}

void S_物体::f_关闭可视通道(uint8 通道) {
	if (m_是否实例 && m_父对象) {
		((S_物体*)(m_父对象))->f_关闭可视通道(通道);
	}
	else {
		switch (m_Type) {
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体: {
			((S_Mesh*)(m_Data[通道]))->m_显示 = false;
			break;
		}
		}
	}
	
}

void S_物体::f_构建底层加速结构() {

}





S_物体* f_get物体(uint32 id_name) {
	if (g_物体容器.f_Key存在(id_name)) {
		return g_物体容器[id_name];
	}
	return nullptr;
}

S_Mesh* f_ob_getMesh(const S_物体* froObj, uint32 loc) {
	if (froObj->m_是否实例) {
		return f_ob_getMesh((S_物体*)(froObj->m_父对象));
	}

	switch (froObj->m_Type) {
		default:
			if (froObj->m_DataNum > loc && froObj->m_Data) {
				return (S_Mesh*)(froObj->m_Data[loc]);
			}
			break;
	}

	return nullptr;
}

S_材质管线* f_ob_get材质(const S_物体* ob, uint32 loc, int32 多维子元素) {
	assert(loc < ob->m_DataNum && ob->m_DataNum);
	auto mesh = (S_Mesh*)(ob->m_Data[loc]);
	return mesh->m_多维材质槽[多维子元素].m_Material;
}

S_Material& f_ob_get材质属性(uint32& 材质ID, const S_物体* ob, uint32 loc, int32 多维子元素) {
	assert(loc < ob->m_DataNum && ob->m_DataNum);
	auto mesh = (S_Mesh*)(ob->m_Data[loc]);
	材质ID = mesh->m_多维材质槽[多维子元素].m_Material->m_材质属性.m_Mem.m_偏移;
	return f_bm_at<S_Material>(mesh->m_多维材质槽[多维子元素].m_Material->m_材质属性);
}


uint32 f_ob_getObType(S_物体* ob) {
	switch (ob->m_Type) {
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体:
			return DEF_ObType_Mesh;
		case E_物体类型::t_粒子系统:
			return DEF_ObType_Particle;
	}
	return 0;
}

//void f_Ob_打开可视通道(uint8 通道) {
//	g_可视[通道] = true;
//}
//void f_Ob_关闭可视通道(uint8 通道) {
//	g_可视[通道] = false;
//}

void f_ob_绘制所有元素(S_物体* ob, S_渲染参数 渲染参数) {
	//assert()
	if (!ob->m_显示) return;

	switch (ob->m_Type) {
		case E_物体类型::t_GL立即模式:
		case E_物体类型::t_实例:
		case E_物体类型::t_摄像机:
		case E_物体类型::t_虚拟体:
		case E_物体类型::t_区域光:
			//case E_物体类型::t_包围盒:
			break;
		default: {
			for (uint32 i = 0; i < ob->m_DataNum; ++i) {
				S_Mesh* me = ((S_Mesh*)(ob->m_Data[i]));
				f_ob_绘制元素(ob, me, 0, 渲染参数, false);
			}
			
			if (ob->m_根实例) return;
			break;
		}
	}

To_跳过绘制:
	//return;
	uint32 num = ob->m_子物体.size();
	auto* objs = ob->m_子物体.data();
	for (uint32 i = 0; i < num; ++i) {
		auto* ob = (S_物体*)(objs[i]);
		f_ob_绘制所有元素(ob, 渲染参数);
	}
}

void f_ob_绘制单个元素(S_物体* ob, S_渲染参数 渲染参数, uint32 绘制元素, bool 多维子元素) {
	//assert()
	if (绘制元素 >= ob->m_DataNum || !ob->m_显示 || ob->m_是否实例) goto To_跳过绘制;

	switch (ob->m_Type) {
		case E_物体类型::t_GL立即模式:
		case E_物体类型::t_实例:
		case E_物体类型::t_摄像机:
		case E_物体类型::t_虚拟体:
		case E_物体类型::t_区域光:
		//case E_物体类型::t_包围盒:
			break;
		default: {
			if (ob->m_是否实例) goto To_跳过绘制;
			S_Mesh* me = ((S_Mesh*)(ob->m_Data[绘制元素]));
			f_ob_绘制元素(ob, me, 绘制元素, 渲染参数, 多维子元素);
			break;
		}
	}

To_跳过绘制:
	//return;
	uint32 num = ob->m_子物体.size();
	auto* objs = ob->m_子物体.data();
	for (uint32 i = 0; i < num; ++i) {
		auto* ob = (S_物体*)(objs[i]);
		if (ob->m_是否实例 == false) f_ob_绘制单个元素(ob, 渲染参数, 绘制元素);
	}
}

void f_ob_绘制单个元素(S_物体* ob, S_渲染参数 渲染参数) {
	//assert()
	if (!ob->m_显示) return;

	switch (ob->m_Type) {
		case E_物体类型::t_GL立即模式:
		case E_物体类型::t_实例:
		case E_物体类型::t_摄像机:
		case E_物体类型::t_虚拟体:
		case E_物体类型::t_区域光:
			//case E_物体类型::t_包围盒:
			break;
		default: {
			
			S_Mesh* me = ((S_Mesh*)(ob->m_Data[0]));
			f_ob_绘制元素(ob, me, 0, 渲染参数, false);

			if (ob->m_根实例) return;
			break;
		}
	}

To_跳过绘制:
	//return;
	uint32 num = ob->m_子物体.size();
	auto* objs = ob->m_子物体.data();
	for (uint32 i = 0; i < num; ++i) {
		auto* ob = (S_物体*)(objs[i]);
		f_ob_绘制单个元素(ob, 渲染参数);
	}
}

void f_ob_绘制选择元素(S_物体* ob, S_渲染参数 渲染参数, uint32 绘制元素) {
	if (绘制元素 >= ob->m_DataNum || !ob->m_显示 || ob->m_是否实例 || !ob->m_选中) goto To_跳过绘制;

	switch (ob->m_Type) {
		case E_物体类型::t_GL立即模式:
		case E_物体类型::t_实例:
		case E_物体类型::t_摄像机:
		case E_物体类型::t_虚拟体:
			break;
		default: {
			S_Mesh* me = ((S_Mesh*)(ob->m_Data[绘制元素]));
			f_ob_绘制元素(ob, me, 绘制元素, 渲染参数, false);
			break;
		}
	}

To_跳过绘制:
	uint32 num = ob->m_子物体.size();
	auto* objs = ob->m_子物体.data();
	for (uint32 i = 0; i < num; ++i) {
		auto* ob = (S_物体*)(objs[i]);
		if (ob->m_是否实例 == false) f_ob_绘制选择元素(ob, 渲染参数, 绘制元素);
	}
}




static void f_ob_设置光追实例数量(S_物体* ob, uint32 num) {
	if (f_buf_getGlobal().g_实例AS_0) {
		if (ob->m_光追实例加速结构.m_Buf) {
			f_bm_resize(ob->m_光追实例加速结构, num);
			f_bm_resize(ob->m_物体属性, num);
		}
		else {
			ob->m_光追实例加速结构 = f_bm_alloc(f_buf_getGlobal().g_实例AS_0, num);
			ob->m_物体属性 = f_bm_alloc(f_buf_getGlobal().g_光追物体实例属性ID, num);
		}
	}
}

void f_ob_创建矩阵(S_物体* ob, uint32 num) {
	ob->m_变换矩阵 = f_bm_alloc(ob->m_Ctx.m_几何图形->m_3DGPU缓存_变换, num);
	
	f_ob_设置光追实例数量(ob, num);

	//for (uint32 i = 0; i < ob->m_DataNum; ++i) {
	//	ob->m_实例颜色[i] = f_bm_alloc(f_buf_getGlobal().g_物体颜色[i], num);
	//}

	//ob->m_变换矩阵.m_Buf->m_分配块内存锁.lock();
	//f_buf_Mat44_at(ob->m_变换矩阵, ob->m_实例ID) = f_mat44_identity();
	//ob->m_变换矩阵.m_Buf->m_分配块内存锁.unlock();

	

	//ob->m_变换ID = ob->m_变换矩阵.m_Mem.m_偏移;
	//ob->m_UpdateGPU参数布局 = true;

}

void f_ob_添加矩阵(S_物体* ob, uint32 插入位置) {
	if (插入位置 == -1) {
		插入位置 = ob->m_变换矩阵.m_Mem.m_数量;
	}
	
	auto mat = f_mat44_identity();
	//f_buf_push_back(ob->m_变换矩阵, (uint8*)&mat, 1);
	f_bm_insert(ob->m_变换矩阵, 插入位置, (uint8*)&mat, 1);
	f_ob_设置光追实例数量(ob, ob->m_变换矩阵.m_Mem.m_数量);


	uint32 color = f_PackData4X8({128, 128, 128, 255});
	for (uint32 i = 0; i < ob->m_DataNum; ++i) {
		f_buf_push_back(ob->m_实例颜色[i], (uint8*)&color, 1);
	}

	ob->m_变换ID = ob->m_变换矩阵.m_Mem.m_偏移;
}

void f_ob_set实例数量(S_物体* ob, uint32 num, bool 创建物体) {
	ob->m_是否实例 = false;

	if (创建物体) {
		//ob->m_子物体.resize(num);
	}

	f_bm_resize(ob->m_变换矩阵, num);
	f_ob_设置光追实例数量(ob, num);

	for (uint32 i = 0; i < ob->m_DataNum; ++i) {
		f_bm_resize(ob->m_实例颜色[i], num);
	}
	if (num > 1) ob->m_根实例 = true;
}

void f_ob_删除矩阵(S_物体* ob, uint32 loc, uint32 num) {
	f_buf_erase(ob->m_变换矩阵, loc, num);
}

void f_ob_清除矩阵(S_物体* ob, uint32 num) {
	f_buf_erase(ob->m_变换矩阵, 0, num);
	for (uint32 i = 0; i < ob->m_DataNum; ++i) {
		f_buf_erase(ob->m_实例颜色[i], 0, num);
	}
}



void f_ob_set矩阵(S_物体* ob, const Mat44f& mat, uint32 实例ID) {
	if (ob->m_变换矩阵.m_Mem.m_数量 > 实例ID) {
		f_buf_Mat44_at(ob->m_变换矩阵, 实例ID) = mat;
	}
	else if (ob->m_父对象) {
		f_ob_set矩阵((S_物体*)(ob->m_父对象), mat, 实例ID);
	}
	ob->m_isUpdateMatrix = true;
}

void f_ob_set矩阵(S_物体* ob, const Mat44f* mat, uint32 num) {
	f_bm_fill(ob->m_变换矩阵, mat, num);
}

void f_ob_set颜色(S_物体* ob, const uint32* color, uint32 num, uint32 槽) {
	f_bm_fill(ob->m_实例颜色[槽], color, num);
}

void f_ob_绘制元素(S_物体* ob, S_Mesh* me, uint32 绘制元素, S_渲染参数& 渲染参数, bool 多维子元素) {
	uint32 obType = f_ob_getObType(ob);

	for (uint32 i = 0; i < me->m_多维材质数量; ++i) {
		f_mesh_构建网格属性参数(ob, me, obType);
		f_buf_网格引用_at(*me->m_网格属性, 0).m_Location = me->m_包围盒->pos;


		//uint32 面索引偏移;
		if (me->m_元素->m_多维元素数量 > 0 && 多维子元素) {
			uint32 fo = me->m_多维材质槽[i].m_区间槽索引;

			渲染参数.m_索引内存偏移 = me->m_元素->m_元素区间[fo].x + me->m_索引->m_Mem.m_偏移;
			渲染参数.m_索引内存数量 = me->m_元素->m_元素区间[fo].y;
			assert(渲染参数.m_索引内存偏移 + 渲染参数.m_索引内存数量 <= me->m_索引->m_Buf->m_Size);
		}
		else {
			渲染参数.m_索引内存偏移 = me->m_索引->m_Mem.m_偏移;
			渲染参数.m_索引内存数量 = me->m_索引->m_Mem.m_数量;
		}

		assert(me->m_绘制内存属性);
		if (me->m_绘制内存属性) {
			const S_GPU内存块* 物体参数[2] = { &ob->m_变换矩阵, &ob->m_实例颜色[绘制元素] };
			me->mf_绘制参数设置(me, 物体参数, 多维子元素 ? i : 0);
			
			if (ob->m_骨架) ((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->BonePoseOffset = ob->m_骨架->m_姿态.m_Mem.m_偏移;
		}
		

		auto& material = me->m_多维材质槽[i].m_Material;
		material->mf_GPU参数配置(material, ob, me, 绘制元素, i);
		
		if (material->m_独立统一缓存) {
			me->m_多维材质槽[i].m_参数槽.m_参数槽[0] = &(ob->m_变换矩阵);
			me->m_多维材质槽[i].m_参数槽.m_参数类型[0] = E_板载缓存类型::e_SSBO;
			me->m_多维材质槽[i].m_参数槽.m_绑定位置[0] = 1;
			me->m_多维材质槽[i].m_参数槽.m_绑定数量[0] = 1;

			//f_df_setGPU参数布局(me->m_Ctx.m_逻辑设备.设备, me->m_多维材质槽[i].m_参数槽);
			//(_S_GPU布局描述*)me->m_多维材质槽[i].m_参数槽.m_GPU布局描述;
			f_df_upGPU参数(me->m_Ctx.m_逻辑设备.设备, me->m_多维材质槽[i].m_参数槽);
		}
		else {
			me->m_多维材质槽[i].m_参数槽.m_参数槽[0] = 渲染参数.m_视图投影矩阵;
			me->m_多维材质槽[i].m_参数槽.m_参数类型[0] = E_板载缓存类型::e_UBO;
			me->m_多维材质槽[i].m_参数槽.m_绑定位置[0] = 0;
			me->m_多维材质槽[i].m_参数槽.m_绑定数量[0] = 1;

			me->m_多维材质槽[i].m_参数槽.m_参数槽[1] = &(ob->m_变换矩阵);
			me->m_多维材质槽[i].m_参数槽.m_参数类型[1] = E_板载缓存类型::e_SSBO;
			me->m_多维材质槽[i].m_参数槽.m_绑定位置[1] = 1;
			me->m_多维材质槽[i].m_参数槽.m_绑定数量[1] = 1;

			f_df_upGPU参数(me->m_Ctx.m_逻辑设备.设备, material->m_着色线管->m_GPU参数set, me->m_多维材质槽[i].m_参数槽);
		}
		
		
		
		渲染参数.m_线宽 = me->m_线宽;
		渲染参数.m_实例数量 = ob->m_变换矩阵.m_Mem.m_数量;
		渲染参数.m_实例偏移 = 0;
		
		
		if (me->m_间接 && me->m_间接->m_Mem.m_数量) {
			f_buf_Indirect_ptr(*me->m_间接)->firstInstance = 0;
		}
		渲染参数.m_间接 = me->m_间接;
		
		me->f_绘制(渲染参数, i);
	}
}



S_物体* f_ob_创建网格物体(S_设备环境 ctx) {
	S_物体* ob = new S_物体(E_物体类型::t_网格物体);
	f_ob_创建矩阵(ob);
	return ob;
}

Mat44f f_ob_get实例变换矩阵(S_物体* Obj, uint32 ID) {
	if (ID < Obj->m_变换矩阵.m_Mem.m_数量) {
		return f_buf_Mat44_at(Obj->m_变换矩阵, ID);
	}
	else {
		if (Obj->m_父对象) {
			return f_ob_get实例变换矩阵((S_物体*)(Obj->m_父对象), ID);
		}
	}
	return f_mat44_identity();
}

Mat44f f_ob_get变换矩阵(const S_物体* ob, uint32 ID) {
	Mat44f mat;
	if (ob->m_变换矩阵.m_Mem.m_数量) {
		return f_buf_Mat44_at(ob->m_变换矩阵, ID);
	}
	else {
		if (ob->m_父对象) return f_ob_get变换矩阵((S_物体*)(ob->m_父对象), ID);
		mat = f_mat44_identity();
	}
	return mat;
}
mat4 f_ob_getMatrix(const S_物体* ob, uint32 ID) {
	mat4 mat;
	if (ob->m_变换矩阵.m_Mem.m_数量) {
		return f_bm_at<mat4>(ob->m_变换矩阵, ID);
	}
	else {
		if (ob->m_父对象) return f_ob_getMatrix((S_物体*)(ob->m_父对象), ID);
	}
	return f_mat4_identity();
}



//Mat44f f_ob_get独立计算变换矩阵(S_物体* ob) {
//	Mat44f 父矩阵;
//	if (ob->m_父物体) {
//		父矩阵 = f_ob_get独立计算变换矩阵((S_物体*)(ob->m_父物体));
//	}
//	else {
//		父矩阵 = f_mat44_identity();
//	}
//
//	Mat44f mat;
//	f_物体变换生成(ob, &mat, &父矩阵);
//	return mat;
//}


Mat44f f_ob_get父对象变换矩阵(S_物体* Obj, uint32 depth, bool 包含顶层) {
	if (Obj->m_父对象) {
		++depth;
 
		switch (Obj->m_Type) {
			case E_物体类型::t_实例:
			case E_物体类型::t_骨架:
			case E_物体类型::t_骨骼:
			case E_物体类型::t_虚拟体:
			case E_物体类型::t_点光源:
			case E_物体类型::t_聚光灯:
				return f_ob_get父对象变换矩阵((S_物体*)(Obj->m_父对象), depth);
			default:
				break;
		}

		if (!( ((S_物体*)(Obj->m_父对象))->m_变换矩阵.m_Mem.m_数量) ) {
			return f_ob_get父对象变换矩阵((S_物体*)(Obj->m_父对象), depth);
		}

		//if (Obj->m_父对象->m_Type == E_物体类型::t_实例) {
		//	return f_ob_get实例变换矩阵((S_物体*)(Obj->m_父对象), Obj->m_实例ID);
		//}
	}

	if (包含顶层 || depth) {
		return f_ob_get实例变换矩阵(Obj, Obj->m_实例ID);
	}

	return f_mat44_identity();
}

S_Cube f_ob_get包围盒(const Mat44f& mat, const S_Bounding& bound) {
	vec3 最小 = mat * bound.min;
	vec3 最大 = mat * bound.max;

	vec3 变换后最小 = vec_Min(最小, 最大);
	vec3 变换后最大 = vec_Max(最小, 最大);

	S_Cube 包围盒;
	包围盒.pos = 变换后最小;
	包围盒.size = (变换后最大 - 变换后最小);
	包围盒.pos += 包围盒.size * 0.5;

	return 包围盒;
}

S_Bounding f_ob_get世界包围盒(S_物体* ob, uint32 槽, uint32 实例) {
	S_Bounding box{};
	
	S_Mesh* mesh = f_ob_get数据(ob, 槽).m_Mesh;

	auto mat = f_ob_get实例变换矩阵(ob, 实例);

	box.min = mat * mesh->f_getBound().min;
	box.max = mat * mesh->f_getBound().max;

	return box;
}

vec3 f_ob_get世界中心(S_物体* ob, uint32 槽) {
	if (ob->m_DataNum) {
		S_Mesh* mesh = (S_Mesh*)(ob->m_Data[槽]);

		auto mat = f_ob_get实例变换矩阵(ob, ob->m_实例ID);
		const auto& 元素变换属性 = f_buf_网格元素变换属性_at(mesh->m_网格元素变换属性, 0);
	
		vec3 最小 = mat * mesh->f_getBound().min;
		vec3 最大 = mat * mesh->f_getBound().max;
		S_Cube cube;
		cube.pos = 最小;
		cube.size = (最大 - 最小);
		cube.pos += cube.size * 0.5;

		return cube.pos;
	}
	
	return ob->m_变换.position;
}

uint32 f_ob_get中心和(S_物体* ob, vec3& 中心和) {
	中心和 += f_ob_get世界中心(ob, ob->m_网格拾取元素);

	uint32 num = ob->m_子物体.size();
	for (auto& e : ob->m_子物体) {
		num += f_ob_get中心和((S_物体*)(e), 中心和);
	}
	return num;
}

E_物体类型 f_ob_get实例父类型(S_物体* ob) {
	if (ob->m_父对象 && ob->m_Type == E_物体类型::t_实例) {
		//switch (ob->m_Type) {
		//
		//}
		return f_ob_get实例父类型(ob);
	}
	return ob->m_Type;
}

S_物体* f_ob_get实例父对象(S_物体* ob) {
	if (ob->m_父对象 && ob->m_Type == E_物体类型::t_实例) {
		return f_ob_get实例父对象((S_物体*)(ob->m_父对象));
	}
	return ob;
}

vec3 f_ob_get全局旋转(S_物体* ob, vec3 旋转方向, uint32 实例) {
	auto mat = f_buf_Mat44_at(ob->m_变换矩阵, 实例);
	auto rot = f_mat44_to_33(mat);

	return rot * 旋转方向;
}











void f_ob_步进时间帧(float32 f) {
	//S_物体::g_前一帧 = S_物体::g_当前帧;
	//S_物体::g_当前帧 += f;

	g_帧时间改变 = true;
}

void f_ob_set步进时间帧(float64 f) {
	//S_物体::g_前一帧 = S_物体::g_当前帧;
	//S_物体::g_当前帧 = f;

	g_帧时间改变 = true;
}

Mat44f f_ob_构建XYZ变换矩阵euler(const S_物体* ob) {
	C_Mat44 mat = C_Mat44::kIdentity;
	Mat44f m = f_mat44_identity();

	auto rx = f_构建旋转矩阵(ob->m_变换.rotation.x, { 1.0f,0.0f,0.0f });
	auto ry = f_构建旋转矩阵(ob->m_变换.rotation.y, { 0.0f,1.0f,0.0f });
	auto rz = f_构建旋转矩阵(ob->m_变换.rotation.z, { 0.0f,0.0f,1.0f });
	auto s = f_mat4_构建缩放矩阵(ob->m_变换.scale);

	mat *= rx;
	mat *= ry;
	mat *= rz;

	m = *((Mat44f*)&mat);
	return m;
}

Mat44f f_ob_构建XYZ变换矩阵euler(const vec3& rot) {
	C_Mat44 mat = C_Mat44::kIdentity;
	Mat44f m = f_mat44_identity();

	auto rx = f_构建旋转矩阵(rot.x, { 1.0f,0.0f,0.0f });
	auto ry = f_构建旋转矩阵(rot.y, { 0.0f,1.0f,0.0f });
	auto rz = f_构建旋转矩阵(rot.z, { 0.0f,0.0f,1.0f });

	mat *= rx;
	mat *= ry;
	mat *= rz;

	m = *((Mat44f*)&mat);
	return m;
}


S_骨骼IK* f_ob_创建IK() {
	S_骨骼IK* ik = (S_骨骼IK*)malloc(sizeof(S_骨骼IK));
	(*ik) = {};
	ik->m_迭代次数 = 1;
	ik->m_使用骨节坐标 = false;
	ik->m_深度 = 0;
	return ik;
}

void f_ob_销毁IK(S_骨骼IK* ik) {
	free(ik);
}

S_骨骼IK** f_ob_添加IK(S_骨架* 骨骼, uint16 IK数量) {
	骨骼->m_IK = (S_骨骼IK**)calloc(IK数量, sizeof(S_骨骼IK*));
	骨骼->m_IK数量 = IK数量;
	return 骨骼->m_IK;
}

S_骨架* f_ob_创建骨架() {
	S_骨架* 骨架 = (S_骨架*)malloc(sizeof(S_骨架));

	骨架->m_姿态 = f_bm_alloc(S_物体::g_骨骼姿态, 0);
	骨架->m_骨骼邻接 = (S_骨骼邻接数组*)f_core_array_new(0, sizeof(S_骨骼邻接*));
	//骨架->m_骨骼长度 = f_buf_alloc(S_物体::g_骨骼长度, 0);
	//骨架->m_初始姿态 = f_buf_alloc(S_物体::g_姿态变换, 0);
	//骨架->m_变换姿态 = f_buf_alloc(S_物体::g_姿态变换, 0);
	//骨架->m_骨骼变换 = f_buf_alloc(S_物体::g_骨骼变换, 0);


	骨架->m_骨头数量 = 0;
	骨架->m_IK数量 = 0;
	骨架->m_IK = nullptr;

	骨架->m_解算约束 = true;
	return 骨架;
}

void f_ob_销毁骨节(S_骨架* 骨架) {
	f_bm_erase(骨架->m_姿态);
	delete 骨架;
}

S_骨架* f_ob_from骨架(const S_物体* froObj, uint32 loc) {
	
	assert(froObj->m_UserData);
	return (S_骨架*)froObj->m_UserData;

	switch (froObj->m_Type) {
		case E_物体类型::t_骨架:
			return (S_骨架*)(froObj->m_Data[loc]);
	}
	return nullptr;
}




S_物体* f_ob_创建实例(S_物体* froObj) {
	S_物体* ob = new S_物体(E_物体类型::t_实例);
	ob->m_是否实例 = true;
	if (froObj) {
		ob->m_实例ID = froObj->m_子物体.size();
		ob->m_父对象 = froObj;
		froObj->m_根实例 = true;
		froObj->m_isUpdate = true;
		froObj->m_子物体.push_back(ob);
		

		f_ob_set实例数量(froObj, froObj->m_子物体.size());
	}
	return ob;
}

S_骨骼* f_ob_创建骨骼(S_物体* ob, float32 长度) {
	ob->m_Name = u"骨骼";
	
	S_骨骼* 骨骼 = (S_骨骼*)malloc(sizeof(S_骨骼));
	骨骼->m_长度 = 长度;
	骨骼->m_旋转 = vec4{ 0,0,0,1 };
	骨骼->m_动态旋转 = vec4{ 0,0,0,1 };
	骨骼->m_初始头坐标 = {};

	//f_ob_set数据(ob, 骨骼);
	骨骼->m_骨节A = nullptr;
	骨骼->m_骨节B = f_ob_创建实例();
	骨骼->m_根骨骼 = nullptr;

	骨骼->m_IK = nullptr;
	骨骼->m_IK关联数量 = 0;

	骨骼->m_对称物体 = nullptr;
	骨骼->m_对称偏移 = {};
	骨骼->m_对称方向 = -1;

	骨骼->m_封套范围线 = nullptr;


	S_骨节* 骨节 = new S_骨节;
	骨节->m_Type = 0;
	骨节->m_封套大小 = -1;
	骨节->m_骨节初始尾坐标 = {};
	骨骼->m_骨节B->m_UserData = 骨节;


	ob->m_UserData = 骨骼;
	return 骨骼;
}

S_物体* f_ob_创建骨骼(S_物体* 父物体, S_设备环境& ctx, float32 长度) {
	S_物体* ob = new S_物体(E_物体类型::t_骨骼);
	ob->m_Name = u"骨骼";
	//f_ob_set数据槽数量(ob, 1);
	f_ob_创建矩阵(ob);

	f_ob_创建骨骼(ob, 长度);
	//S_骨骼* 骨骼 = (S_骨骼*)malloc(sizeof(S_骨骼));
	//骨骼->m_长度 = 长度;
	//骨骼->m_旋转 = vec4{ 0,0,0,1 };
	//骨骼->m_动态旋转 = vec4{ 0,0,0,1 };
	////f_ob_set数据(ob, 骨骼);
	//骨骼->m_骨节A = nullptr;
	//骨骼->m_骨节B = f_ob_创建实例();
	//骨骼->m_根骨骼 = nullptr;
	//骨骼->m_IK关联数量 = 0;
	//
	//S_骨节* 骨节 = new S_骨节;
	//骨节->m_Type = 0;
	//骨节->m_封套大小 = -1;
	//骨节->m_骨节初始根坐标 = {};
	//骨骼->m_骨节B->m_UserData = 骨节;
	//
	//ob->m_UserData = 骨骼;
	return ob;
}


static S_物体* f_ob_查找IK旋转向量中间骨骼(S_物体* 骨骼, S_骨骼IK* IK, uint32& depth) {
	if (骨骼->m_父对象) {
		++depth;
		if (骨骼->m_父对象 == IK->m_始端) {
			goto To_根骨骼;
		}
		else {
			S_物体* r_ob = f_ob_查找IK旋转向量中间骨骼((S_物体*)(骨骼->m_父对象), IK, depth);
			if (r_ob) {
				return r_ob;
			}
		}
	}
	else {
	To_根骨骼:
		depth = 骨骼->m_实例ID;
		return 骨骼;
	}
	return nullptr;
}




void f_ob_ge骨节坐标(S_物体* 根骨骼, vec3* 骨节坐标, const Mat44f* 骨骼变换矩阵, const float32* 骨骼长度, const Mat44f& 父级变换) {
	uint32 num = 根骨骼->m_子物体.size();

	uint32 offset = 根骨骼->m_实例ID;
	骨节坐标[offset] = 骨骼变换矩阵[offset] * vec3{ 0, 0, 骨骼长度[offset] };
	骨节坐标[offset] = 父级变换 * 骨节坐标[offset];

	for (uint32 i = 0; i < num; ++i) {
		S_物体* ob = (S_物体*)(根骨骼->m_子物体[i]);

		f_ob_ge骨节坐标(ob, 骨节坐标, 骨骼变换矩阵, 骨骼长度, 父级变换);
	}
}


vec3 f_ob_计算骨骼IK点(S_物体* ob, bool 尾部) {

	auto mat = f_ob_get父对象变换矩阵(ob, ob->m_实例ID);
	S_骨骼* 骨骼 = f_ob_from骨骼(ob);

	vec3 coord;
	if (尾部) {
		coord = (mat * f_mat44_构建移动矩阵({ 0, 0, 骨骼->m_长度 })) * vec3{};
	}
	else {
		coord = mat * vec3{};
	}
	return coord;
}

vec3 f_ob_计算骨骼IK中点(S_骨骼IK* IK) {
	vec3 vs = {};
	vec3 ve = {};
	if (IK->m_始端) vs = f_ob_计算骨骼IK点(IK->m_始端, false);
	if (IK->m_始端) ve = f_ob_计算骨骼IK点(IK->m_末端, true);

	return vs + (ve - vs) * 0.5f;

	if (IK->m_末端) {
		uint32 中点ID = 0;
		S_物体* ob = f_ob_查找IK旋转向量中间骨骼(IK->m_末端, IK, 中点ID);
		auto mat = f_ob_get父对象变换矩阵(IK->m_末端, 中点ID);

		S_骨骼* 骨骼 = f_ob_from骨骼(ob);
		return (mat * f_mat44_构建移动矩阵({ 0, 0, 骨骼->m_长度 })) * vec3 {};
		return mat * vec3 {};
	}
	return {};
}


void f_ob_从骨节更新编辑骨骼(S_物体* 根骨骼
	, vec3* 骨节
	, const float32* 骨骼长度
	, Mat44f* 骨骼物体变换矩阵
	, const vec4& 父骨骼旋转
	, const Mat44f& 父矩阵
	, const vec3& s
	, float32 l) {

	uint32 num = 根骨骼->m_子物体.size();
	

	vec3 e = 骨节[根骨骼->m_实例ID];


	vec3 骨骼方向 = e - s;
	骨骼方向 = f_graph_quat变换坐标(f_graph_quat反向(父骨骼旋转), 骨骼方向);
	vec4 q = f_graph_quat两向量(骨骼方向, DEF_骨骼朝向);
	vec3 rot = f_graph_四元数转欧拉角(q);
	rot = vec3{ -rot.x, -rot.y, rot.z };


	S_Tranform tran = 根骨骼->m_变换;
	//f_TranformInit(tran);
	if (根骨骼->m_实例ID) {
		tran.position = { 0, 0, l };
	} else {
		tran.position = s;
	}
	
	tran.rotation = rot;
	骨骼物体变换矩阵[根骨骼->m_实例ID] = 父矩阵 * f_mat44_构建XYZ变换矩阵(tran);

	vec4 newQuat = f_graph_quatNormalize(f_graph_quat相乘(q, 父骨骼旋转));

	for (uint32 i = 0; i < num; ++i) {
		S_物体* 骨骼 = (S_物体*)(根骨骼->m_子物体[i]);
		S_骨骼* 骨骼数据 = f_ob_from骨骼(骨骼);

		f_ob_从骨节更新编辑骨骼(骨骼, 骨节, 骨骼长度, 骨骼物体变换矩阵, newQuat, 骨骼物体变换矩阵[根骨骼->m_实例ID], e, 骨骼长度[根骨骼->m_实例ID]);
	}
}



void f_ob_准备解算IK关联骨骼(S_骨骼IK* IK) {
	S_物体* ob = IK->m_末端;
	
	for (;;) {
		S_骨骼* 骨骼 = f_ob_from骨骼(ob);
		骨骼->m_骨节B->m_变换.position = f_ob_from骨节(骨骼)->m_骨节初始尾坐标;
		骨骼->m_IK关联数量 = 0;
		
		if (!(ob->m_父对象) || ob == IK->m_始端) {
			break;
		}
		ob = (S_物体*)(ob->m_父对象);
	}
}

void f_ob_准备解算IK关联骨骼(S_物体* ob) {
	for (auto& e : ob->m_子物体) {
		auto* ob = (S_物体*)(e);
		ob->m_变换.position = f_ob_from骨节(ob)->m_骨节初始尾坐标;
	}
}

void f_ob_解算IK骨节步进坐标(S_骨骼IK* IK, const vec3& 父物体坐标偏移, const Mat44f& mat) {
	S_物体* ob = IK->m_末端;
	//vec3 末点坐标 = f_ob_get对象世界坐标(IK->m_末端坐标) - 父物体坐标偏移;
	vec3 末点坐标 = f_ob_get对象世界坐标(IK->m_末端坐标);
	末点坐标 = mat * 末点坐标;
	
	for (; ;) {
		if (!(ob->m_父对象) || ob == IK->m_始端 || ((S_物体*)(ob->m_父对象))->m_Type != E_物体类型::t_骨骼 ) {
			break;
		}
		S_骨骼* 骨骼 = f_ob_from骨骼(ob);
		S_骨节* 骨节 = f_ob_from骨节(骨骼->m_骨节B);

		S_骨骼* 父骨骼 = f_ob_from骨骼((S_物体*)(ob->m_父对象));
		vec3 骨骼向量 = 骨骼->m_骨节B->m_变换.position - 父骨骼->m_骨节B->m_变换.position;
		骨骼->m_骨节B->m_变换.position = 末点坐标;
		骨骼->m_IK关联数量 = 1;

		
		vec3 骨节偏移向量 = 末点坐标 - 父骨骼->m_骨节B->m_变换.position;
		骨节偏移向量 += 骨骼向量;


		末点坐标 = 末点坐标 - vec_normalize(骨节偏移向量) * 骨骼->m_长度;
		ob = (S_物体*)(ob->m_父对象);
	}
}

static void f_ob_修正IK骨节距离(S_物体* ob, vec3 offset) {
	S_骨骼* 骨骼 = f_ob_from骨骼(ob);
	S_骨节* 骨节 = f_ob_from骨节(骨骼);
	
	
	for (auto& 根骨骼 : ob->m_子物体) {
		S_骨骼* 子骨骼 = f_ob_from骨骼((S_物体*)(根骨骼));
		S_骨节* 子骨节 = f_ob_from骨节(子骨骼);

		vec3 累加偏移 = offset;
		if (骨骼->m_IK关联数量 >= 1 && 子骨骼->m_IK关联数量 <= 0) {
			//累加偏移 += 子骨节->m_骨节坐标 - 子骨骼->m_骨节B->m_变换.location;
			//累加偏移 += 骨节->m_骨节坐标 - 骨骼->m_骨节B->m_变换.location;
			累加偏移 += 骨骼->m_骨节B->m_变换.position - 骨节->m_骨节初始尾坐标;

			子骨骼->m_骨节B->m_变换.position = 子骨节->m_骨节初始尾坐标 + 累加偏移;
		}
		else {
			子骨骼->m_骨节B->m_变换.position += 累加偏移;
		}
		

		f_ob_修正IK骨节距离((S_物体*)(根骨骼), 累加偏移);
	}
}

void f_ob_修正IK骨节距离(S_物体* ob) {
	S_物体* 骨节 = (S_物体*)(ob->m_子物体.back());

	for (auto& 根骨骼 : ob->m_子物体) {
		if ( ((S_物体*)(根骨骼))->m_Type == E_物体类型::t_骨骼 ) {
			f_ob_修正IK骨节距离((S_物体*)(根骨骼), {});
		}
	}
}

void f_ob_解算骨骼IK(S_物体* ob) {
	S_骨架 * 骨架 = f_ob_from骨架(ob);
	if (!骨架->m_IK数量) return;

	vec3 父坐标 = f_ob_get对象世界坐标(ob);
	//auto mat = f_mat44_Inverse(f_ob_get变换矩阵(ob, ob->m_实例ID));
	auto mat = f_mat44_Invert(f_ob_get变换矩阵(ob, ob->m_实例ID));
	

	//S_物体* 骨节 = ob->m_子物体.back();
	for (auto& e : ob->m_子物体) {
		auto* ob = (S_物体*)(e);
		if(ob->m_Type == E_物体类型::t_骨节) {
			f_ob_准备解算IK关联骨骼(ob);
			break;
		}
	}
	
	//float32 挤压比例 = 1;
	for (uint32 k = 0; k < 8; ++k) {
		
		for (uint32 i = 0; i < 骨架->m_IK数量; ++i) {
			S_骨骼IK* IK = 骨架->m_IK[i];

			if (IK && IK->m_始端 && IK->m_末端) {
				f_ob_解算IK骨节步进坐标(IK, 父坐标, mat);
			}
		}

		f_ob_从骨节更新骨骼(ob);
		f_ob_从骨骼更新骨节(ob);
		//挤压比例 /= 12;
	}

	//f_ob_修正IK骨节距离(ob);
	//f_ob_从骨节更新骨骼(ob);
	
}



void f_ob_从骨节更新骨骼(S_物体* 骨架) {
	S_物体* 骨节 = (S_物体*)(骨架->m_子物体.back());

	for (auto& 根骨骼 : 骨架->m_子物体) {
		auto* ob = (S_物体*)(根骨骼);
		if (ob->m_Type == E_物体类型::t_骨骼) {
			f_ob_从骨节构建骨骼(ob, (S_物体*)(ob->m_子物体.back()), { 0,0,0,1 }, 0);
		}
	}
}

void f_ob_从骨节构建骨骼(S_物体* 根骨骼, S_物体* 骨节, const vec4& 父骨骼旋转, const float32 父骨骼长度) {
	uint32 num = 根骨骼->m_子物体.size();
	S_骨骼* 骨骼 = f_ob_from骨骼(根骨骼);

	vec3 s = 骨骼->m_骨节B->m_变换.position;

	for (uint32 i = 0; i < num; ++i) {
		S_物体* 末端骨骼 = (S_物体*)(根骨骼->m_子物体[i]);
		if (末端骨骼->m_Type != E_物体类型::t_骨骼) continue;

		S_骨骼* 骨骼数据 = f_ob_from骨骼(末端骨骼);
		vec3 e = 骨骼数据->m_骨节B->m_变换.position;
		vec3 骨骼方向 = vec_normalize(e - s);


		骨骼方向 = f_graph_quat变换坐标(f_graph_quat反向(父骨骼旋转), 骨骼方向);
		vec4 q = f_graph_quat两向量(骨骼方向, DEF_骨骼朝向);
		vec3 rot = f_graph_四元数转欧拉角(q);

		rot = vec3{ -rot.x, -rot.y, rot.z };
		末端骨骼->f_set旋转(rot, 0);
		末端骨骼->f_set缩放({ 1, 1 ,1 }, 0);
		骨骼数据->m_动态旋转 = q;


		vec4 newQuat = f_graph_quatNormalize(f_graph_quat相乘(q, 父骨骼旋转));
		f_ob_从骨节构建骨骼(末端骨骼, 骨节, newQuat, 骨骼数据->m_长度);
	}
}

static void f_构建骨节坐标(S_物体* 骨骼, const vec3& 父坐标, const vec4& q) {
	S_骨骼* 骨骼对象 = f_ob_from骨骼(骨骼);

	vec3 偏移 = { 0, 0, 骨骼对象->m_长度 };
	
	vec4 q_a = f_graph_quat相乘(骨骼对象->m_动态旋转, q);
	vec3 骨节坐标 = f_graph_quatTranformInv(q_a, 偏移);
	骨节坐标 += 父坐标;

	骨骼对象->m_骨节B->m_变换.position = 骨节坐标;


	for (auto& e : 骨骼->m_子物体) {
		auto* ob = (S_物体*)(e);
		if(ob->m_Type != E_物体类型::t_骨骼) continue;

		f_构建骨节坐标(ob, 骨节坐标, q_a);
	}
}

void f_ob_从骨骼更新骨节(S_物体* 骨架物体) {
	int32 num = 骨架物体->m_子物体.size() - 1;
	if(num < 1) return;

	//auto& 骨节 = 骨架物体->m_子物体.back()->m_子物体;
	for (auto& e : 骨架物体->m_子物体) {
		auto* ob = (S_物体*)(e);
		if (ob->m_Type == E_物体类型::t_骨骼) {
			f_构建骨节坐标(ob, ob->m_变换.position, { 0,0,0,1 });
		}
		//else if (e->m_Type == E_物体类型::t_骨节) {
		//	e->m_isUpdate = true;
		//}
		else {
			ob->m_isUpdate = true;
		}
	}
	//骨架物体->m_子物体.back()->m_isUpdate = true;
}

void f_ob_骨节复位(S_物体* 骨架物体) {
	S_物体* 骨节物体 = (S_物体*)(骨架物体->m_子物体.back());

	for (auto& 骨节 : 骨节物体->m_子物体) {
		((S_物体*)(骨节))->m_变换.position = f_ob_from骨节((S_物体*)(骨节))->m_骨节初始尾坐标;
	}
}




vec4 f_ob_骨骼旋转计算(S_骨骼* 父骨骼, S_骨骼* 骨骼, S_BonePose& t) {
	vec3 s = 骨骼->m_变换后根坐标;
	vec3 e = 骨骼->m_变换后尾坐标;

	auto* 骨节A = f_ob_from骨节(父骨骼->m_骨节B);
	auto* 骨节B = f_ob_from骨节(骨骼->m_骨节B);

	vec3 骨骼初始方向 = normalize(骨节B->m_骨节初始尾坐标 - 骨节A->m_骨节初始尾坐标);

	vec3 骨骼方向 = normalize(e - s);
	vec4 q = f_graph_quat两向量(骨骼方向, 骨骼初始方向);

	t.quat = q;
	t.tranformBoneA = _Vec4(骨节A->m_骨节初始尾坐标, 骨骼->m_长度);
	t.tranformBoneB = _Vec4(s, t.tranformBoneB.w);
	return q;
}

static void f_ob_构建骨骼GPU数据(S_BonePose* 姿态, const vec3& 根骨骼坐标, S_物体* 骨骼物体, const Mat44f& mat) {
	auto* 父骨骼 = f_ob_from骨骼(骨骼物体);
	vec3 骨节坐标 = f_ob_from骨节(父骨骼)->m_骨节初始尾坐标;

	for (auto& e : 骨骼物体->m_子物体) {
		auto* ob = (S_物体*)(e);

		if (ob->m_Type != E_物体类型::t_骨骼) continue;
		auto* 子骨骼 = f_ob_from骨骼(ob);

		auto& t = 姿态[e->m_ID];
		
		//vec4 q = f_ob_骨骼旋转计算(父骨骼, 子骨骼, t);
		vec3 始端坐标 = 子骨骼->m_变换后根坐标;
		vec3 末端坐标 = 子骨骼->m_变换后尾坐标;
		
		auto* 骨节A = f_ob_from骨节(父骨骼->m_骨节B);
		auto* 骨节B = f_ob_from骨节(子骨骼->m_骨节B);
		
		vec3 骨骼初始方向 = normalize(mat * 骨节B->m_骨节初始尾坐标 - mat * 骨节A->m_骨节初始尾坐标);
		
		vec3 骨骼方向 = normalize(末端坐标 - 始端坐标);
		vec4 q = f_graph_quat两向量(骨骼方向, 骨骼初始方向);
		
		t.quat = q;
		t.tranformBoneA = _Vec4(mat * 骨节A->m_骨节初始尾坐标, 父骨骼->m_长度);
		t.tranformBoneB = _Vec4(始端坐标, t.tranformBoneB.w);
		
		vec3 骨骼坐标 = f_graph_quatTranform(q, { 0, 0, 父骨骼->m_长度 });
		
		f_ob_构建骨骼GPU数据(姿态, 骨骼坐标 + 根骨骼坐标, ob, mat);
	}
}

void f_ob_构建骨骼变换GPU数据(S_骨架* 骨架, const S_物体* 骨架物体, const Mat44f& mat) {
	
	int32 num = 骨架物体->m_子物体.size() - 1;
	if (num < 1 || 骨架->m_姿态.m_Mem.m_数量 <= 0) return;

	S_BonePose* 骨骼姿态 = f_buf_骨骼姿态_ptr(骨架->m_姿态);


	for (auto& e : 骨架物体->m_子物体) {
		auto* ob = (S_物体*)(e);

		if (ob->m_Type == E_物体类型::t_骨骼) {
			auto* 子骨骼 = f_ob_from骨骼(ob);
			auto& t = 骨骼姿态[e->m_ID];

			auto* 骨骼 = f_ob_from骨骼(ob);

			t.tranformBoneA = _Vec4(mat * f_ob_from骨节(骨骼)->m_骨节初始尾坐标, 骨骼->m_长度);
			t.tranformBoneB = _Vec4(mat * 子骨骼->m_骨节B->m_变换.position);

			f_ob_构建骨骼GPU数据(骨骼姿态, 子骨骼->m_骨节B->m_变换.position, ob, mat);
		}
	}
	
}

void f_ob_销毁网格数据(S_物体* ob) {
	for (uint32 i = 0; i < ob->m_DataNum; ++i) {
		f_surface_销毁网格(f_ob_getMesh(ob, i));
	}
}

void f_ob_计算网格包围盒(S_物体* ob) {
	for (uint32 i = 0; i < ob->m_DataNum; ++i) {
		f_mesh_计算包围盒(f_ob_getMesh(ob, i));
	}
}











C_骨骼管理::C_骨骼管理() {

}

C_骨骼管理::~C_骨骼管理() {
	for (auto& e : m_骨骼容器) {
		free(e);
	}
}






struct S_光追渲染层 : public S_渲染层 {
	std::vector<VkAccelerationStructureInstanceKHR> 光追实例变换;
	std::vector<S_RtOb> 光追实例物体;
};

S_渲染层* f_ob_创建渲染层(S_设备环境& ctx) {
	//S_渲染层* 层 = (S_渲染层*)malloc(sizeof(S_渲染层));
	S_光追渲染层* 层 = new S_光追渲染层;

	层->m_Ctx = ctx;
	if (ctx.m_支持光追) {
		//层->m_光追顶层加速结构 = f_bm_alloc(f_buf_getGlobal().g_TLAS_1, 256);
		//层->m_光追实例变换 = f_bm_alloc(f_buf_getGlobal().g_实例AS_0, 0);
		//层->m_光追实例物体 = f_bm_alloc(f_buf_getGlobal().g_光追物体实例属性ID, 0);
	}
	else {
		层->m_光追顶层加速结构 = {};
		层->m_光追实例变换 = {};
		层->m_光追实例物体 = {};
	}
	层->m_光追描述集 = nullptr;

	//层->m_光追顶层加速结构 = f_buf_create板载缓存(ctx, E_板载缓存类型::e_SSBO, E_板载缓存类型::e_SSBO | E_板载缓存类型::e_着色端内存地址, sizeof(VkAccelerationStructureInstanceKHR), 1);
	return 层;
}

void f_ob_销毁渲染层(S_渲染层* 层) {
	if (层->m_Ctx.m_支持光追) {
		//f_bm_erase(层->m_光追顶层加速结构);
		//f_bm_erase(层->m_光追实例变换);
		//f_bm_erase(层->m_光追实例物体);
	}
	delete 层;
}

void f_ob_设置渲染层数(S_渲染层* 渲染层, uint32 渲染层数量) {
	
}



S_Mesh* f_ob_get光追网格(S_物体* ob) {
	S_Mesh* me;
	switch (ob->m_Type) {
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体: {
			me = f_ob_getMesh(ob, E_物体网格元素类型::e_MT_光照);
			break;
		}
		case E_物体类型::t_粒子系统: {
			me = nullptr;
			break;
		}
		default: me = nullptr; break;
	}
	return me;
}










void f_ob_构建底层光追加速结构(S_物体* ob) {
	uint32 物体类型 = 0;
	switch (ob->m_Type) {
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体: {
			物体类型 = DEF_ObType_Mesh;

			S_Mesh* me = f_ob_getMesh(ob, E_物体网格元素类型::e_MT_光照);
			if (me && f_surface_构建光追底层加速结构(me, ob->m_Type)) {
				f_mesh_构建网格属性参数(ob, me, 物体类型);
			}
			break;
		}
		case E_物体类型::t_粒子系统: {
			物体类型 = DEF_ObType_Particle;

			S_粒子系统配置* psys = f_ob_fromParticle(ob);
			for (uint32 i = 0; i < psys->m_渲染物体数量; ++i) {
				if (f_surface_构建光追底层加速结构(psys->m_渲染物体网格[i], ob->m_Type)) {
					f_mesh_构建网格属性参数(ob, psys->m_渲染物体网格[i], 物体类型);
				}
			}
			break;
		}
		default:
			break;
	}
}

void f_ob_构建底层层光追加速结构(S_渲染对象** renderOb, uint32 num) {
	std::set<S_Mesh*> 网格;
	for (uint32 i = 0; i < num; ++i) {
		f_ob_构建底层光追加速结构(renderOb[i]->m_物体);
		assert(renderOb[i]->m_物体->m_Type == E_物体类型::t_多边形 || renderOb[i]->m_物体->m_Type == E_物体类型::t_网格物体);
	}
}

void f_ob_构建底层层光追加速结构(S_OBArray* obs) {
	uint32 num = obs->count;
	for (uint32 i = 0; i < num; ++i) {
		f_ob_构建底层光追加速结构(obs->ptr_userData[i]);
	}
}

void f_ob_构建底层层光追加速结构(std::vector<S_Object*>& obs) {
	uint32 num = obs.size();
	for (uint32 i = 0; i < num; ++i) {
		f_ob_构建底层光追加速结构((S_物体*)obs[i]);
	}
}

void f_ob_构建底层层光追加速结构(std::map<std::wstring, S_Object*>& obs) {
	uint32 num = obs.size();
	for (auto& e : obs) {
		f_ob_构建底层光追加速结构((S_物体*)e.second);
	}
}



//Inline uint32 f_渲染层光追实例大小分配(S_渲染层& 渲染层, S_物体* ob, uint32 实例偏移) {
//	uint32 实例数量 = ob->m_变换矩阵.m_Mem.m_数量;
//
//	if (实例偏移 >= 渲染层.m_光追实例变换.m_Mem.m_数量) {
//		f_bm_resize(渲染层.m_光追实例变换, 实例偏移 + 实例数量);
//		f_bm_resize(渲染层.m_光追实例物体, 实例偏移 + 实例数量);
//	}
//
//	return 实例数量;
//}
//
//Inline uint32 f_构建光追实例加速结构(S_渲染层& 渲染层, S_物体* ob, uint32 实例偏移) {
//
//}

void f_ob_构建光追实例加速结构(S_物体* ob, S_渲染层& 渲染层, uint8 mask, uint32 场景遮罩和物体遮罩, uint32& 实例偏移) {
	uint32 obType = 0;
	uint32 SBTRO = 0;
	
	static uint32 空实例材质 = 0;


	std::vector<S_Mesh*> 网格组;
	//S_Mesh* mes[1];
	uint32 网格组数量 = 0;
	switch (ob->m_Type) {
		case E_物体类型::t_粒子系统: {
			obType = DEF_ObType_Particle;

			S_粒子系统配置* psys = f_ob_fromParticle(ob);
			for (uint32 i = 0; i < psys->m_渲染物体数量; ++i) {
				auto* me = psys->m_渲染物体网格[i];
				网格组.emplace_back(me);

				f_mesh_构建网格属性参数(ob, me, obType);
			}
			网格组数量 = psys->m_渲染物体数量;
			srand(psys->m_随机种子);
			break;
		}
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体: {
			obType = DEF_ObType_Mesh;
			//SBTRO = 1;
			auto* me = f_ob_getMesh(ob, E_物体网格元素类型::e_MT_光照);
			if (!me || !me->m_底层光追加速结构->m_Mem.m_数量) return;

			网格组.push_back(me);
			网格组数量 = 1;

			f_mesh_构建网格属性参数(ob, me, obType);
			break;
		}
		default: return;
	}
	

	uint32 实例数量 = ob->m_变换矩阵.m_Mem.m_数量;
	if(!实例数量 || !网格组数量) return;
	if (实例偏移 + 实例数量 > 渲染层.m_光追实例变换.m_Mem.m_数量) {
		f_bm_resize(渲染层.m_光追实例变换, 实例偏移 + 实例数量);
		f_bm_resize(渲染层.m_光追实例物体, 实例偏移 + 实例数量);
	}


	auto* 实例材质 = &空实例材质;
	bool 使用实例材质;
	if (ob->m_实例材质ID.size() >= 实例数量) {
		实例材质 = ob->m_实例材质ID.data();
		使用实例材质 = true;
	}
	else {
		使用实例材质 = false;
	}

	auto ptr_instance = f_buf_实例加速结构_ptr(渲染层.m_光追实例变换);
	auto ptr_obInstance = f_bm_ptr<S_RtOb>(渲染层.m_光追实例物体);



	auto* mat = f_buf_Mat44_ptr(ob->m_变换矩阵);
	for (uint32 i = 0; i < 实例数量; ++i) {
		auto matrix = f_mat3x4_转换(mat[i]);
		auto index = f_get随机UIntRange(0, 网格组数量);
		auto me = 网格组[index];


		ptr_instance[实例偏移].transform = *((VkTransformMatrixKHR*)&matrix);
		ptr_instance[实例偏移].instanceCustomIndex = 实例偏移;
		ptr_instance[实例偏移].mask = mask;
		ptr_instance[实例偏移].instanceShaderBindingTableRecordOffset = SBTRO;
		ptr_instance[实例偏移].flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
		ptr_instance[实例偏移].accelerationStructureReference = f_buf_getOffsetAddress(*me->m_底层光追加速结构);


		ptr_obInstance[实例偏移].m_Address_InstanceAttrIndex = f_buf_getAddress2(ob->m_自定义属性索引);
		ptr_obInstance[实例偏移].m_AddressMesh = me->m_网格属性->m_Mem.m_偏移;
		ptr_obInstance[实例偏移].m_MaterialID = 使用实例材质 ? 实例材质[i] : 0;
		ptr_obInstance[实例偏移].m_InstanceID = i;
		ptr_obInstance[实例偏移].m_SceneMask_ObMask = 场景遮罩和物体遮罩;

		++实例偏移;
	}

}

void f_ob_构建顶层光追加速结构(S_OBArray* obs, S_渲染层* 层) {
	if (obs->count) {
		S_光追渲染层& 渲染层 = *(S_光追渲染层*)层;
		uint32 实例偏移 = 0;

		for (uint32 i = 0; i < obs->count; ++i) {
			f_ob_构建光追实例加速结构(obs->ptr_userData[i], 渲染层, 1, 1 << 16 | 0, 实例偏移);
		}
		f_df_构建顶层光追加速(*层, 实例偏移);
	}
}

void f_ob_构建顶层光追加速结构(std::vector<S_Object*>& obs, S_渲染层* 层) {
	uint32 num = obs.size();
	if (num) {
		S_光追渲染层& 渲染层 = *(S_光追渲染层*)层;
		uint32 实例偏移 = 0;

		for (auto& e : obs) {
			f_ob_构建光追实例加速结构((S_物体*)e, 渲染层, 1, 1 << 16 | 0, 实例偏移);
		}
		f_df_构建顶层光追加速(*层, 实例偏移);
	}
}

void f_ob_构建顶层光追加速结构(std::map<std::wstring, S_Object*>& obs, S_渲染层* 层) {
	uint32 num = obs.size();
	if (num) {
		S_光追渲染层& 渲染层 = *(S_光追渲染层*)层;
		uint32 实例偏移 = 0;

		for (auto& e : obs) {
			f_ob_构建光追实例加速结构(((S_物体*)(e.second)), 渲染层, 1, 1 << 16 | 0, 实例偏移);
		}
		f_df_构建顶层光追加速(*层, 实例偏移);
	}
}

void f_ob_构建顶层光追加速结构(S_渲染层* 层, S_渲染对象** 渲染对象, uint32 num) {
	uint32 实例偏移 = 0;
	S_光追渲染层& 渲染层 = *(S_光追渲染层*)层;

	for (uint32 i = 0; i < num; ++i) {
		assert(渲染对象[i]->m_物体->m_Type == E_物体类型::t_多边形 || 渲染对象[i]->m_物体->m_Type == E_物体类型::t_网格物体);

		f_ob_构建光追实例加速结构(
			渲染对象[i]->m_物体, 
			渲染层,
			渲染对象[i]->m_场景遮罩,
			uint32(渲染对象[i]->m_物体遮罩 << 16) | 渲染对象[i]->m_物体光遮罩,
			实例偏移
		);
	}
	f_df_构建顶层光追加速(*层, 实例偏移);
}

















void f_ob_更新光追底层加速结构(S_设备环境& ctx) {
	if (g更新光追网格数量) {
		for (uint32 i = 0; i < g更新光追网格数量; ++i) {
			f_surface_构建光追底层加速结构(g更新光追网格[i], E_物体类型::t_网格物体);
		}
	}
	g更新光追网格数量 = 0;


	if (g更新变换物体.size()) {
		std::vector<S_GPU内存块*> 光追实例加速结构;
		std::vector<S_GPU内存块*> 光追顶层加速结构;
		光追实例加速结构.reserve(g更新变换物体数量);
		光追顶层加速结构.reserve(g更新变换物体数量);
		
		for (auto& ob : g更新变换物体) {
			//f_ob_构建光追实例加速结构(ob);
			光追实例加速结构.push_back(&(ob->m_光追实例加速结构));
			光追顶层加速结构.push_back(&(ob->m_光追顶层加速结构));
		}
		//f_df_构建顶层光追加速(ctx, 光追实例加速结构, 光追顶层加速结构);
	}
}








void f_ob_更新变换约束(S_物体* ob, const Mat44f* 父级变换) {
	if(!ob->m_isUpdate) return;

	Mat44f 变换 = *父级变换;
	on_物体变换生成(ob, &变换, 父级变换);

	if (ob->m_变换矩阵.m_Buf) {
		f_bm_at<Mat44f>(ob->m_变换矩阵, 0) = 变换;

		if (ob->mf_更新变换) {
			ob->mf_更新变换(ob, 父级变换);
		}
	}

	for (auto& so : ob->m_子物体) {
		f_ob_更新变换约束((S_物体*)so, &变换);
	}

	ob->m_isUpdate = false;
}









//void f_ob_构建光锥顶层加速结构(S_物体** ob, uint32 num, S_设备环境& ctx, S_GPU内存块& 光追顶层加速结构, bool 是否更新) {
//	auto* 绘图配置 = (S_绘图设备配置*)ctx.m_绘图设备配置;
//
//	//std::vector<VkDeviceOrHostAddressConstKHR> 实例数据(num);
//	std::vector<VkAccelerationStructureGeometryKHR> asg(num);
//	for (uint32 i = 0; i < num; ++i) {
//		//实例数据[i] = { f_buf_getOffsetAddress(ob[i]->m_光追实例加速结构) };
//		
//		asg[i].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
//		asg[i].geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
//		asg[i].flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
//		asg[i].geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
//		//asg[i].geometry.instances.arrayOfPointers = VK_FALSE;
//		asg[i].geometry.instances.arrayOfPointers = VK_TRUE;
//		asg[i].geometry.instances.data = { f_buf_getOffsetAddress(ob[i]->m_光追实例加速结构) };
//		
//	}
//	//static uint32 顶层加速结构_交叉分配 = 0;
//	//if (顶层加速结构_交叉分配 & 1) {
//	//	if (!ob->m_光追顶层加速结构.m_Buf) ob->m_光追顶层加速结构 = f_bm_alloc(S_Mesh::g_TLAS_0, 0);
//	//}
//	//else {
//	//	if (!ob->m_光追顶层加速结构.m_Buf) ob->m_光追顶层加速结构 = f_bm_alloc(S_Mesh::g_TLAS_1, 0);
//	//}
//	//++顶层加速结构_交叉分配;
//	//
//	//uint32 实例数量 = DEF_Max(ob->m_变换矩阵.m_Mem.m_数量, 1);
//	//
//	//
//	//VkDeviceOrHostAddressConstKHR 实例数据{};
//	//实例数据.deviceAddress = f_buf_getOffsetAddress(ob->m_光追实例加速结构);
//	//
//	//VkAccelerationStructureGeometryKHR asg{ VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR }; {
//	//	asg.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
//	//	asg.flags = VK_GEOMETRY_OPAQUE_BIT_KHR;
//	//	asg.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
//	//	asg.geometry.instances.arrayOfPointers = VK_FALSE;
//	//	asg.geometry.instances.data = 实例数据;
//	//}
//
//	VkAccelerationStructureBuildGeometryInfoKHR m_加速结构绑定几何实例信息 = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR };
//	m_加速结构绑定几何实例信息.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
//	m_加速结构绑定几何实例信息.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
//	m_加速结构绑定几何实例信息.geometryCount = num;
//	m_加速结构绑定几何实例信息.pGeometries = asg.data();
//
//
//	uint32_t primitive_count = 1;
//	VkAccelerationStructureBuildSizesInfoKHR m_加速结构绑定实例大小信息 = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR };
//	绘图配置->vkGetAccelerationStructureBuildSizes(
//		绘图配置->m_设备,
//		VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
//		&m_加速结构绑定几何实例信息,
//		&primitive_count,
//		&m_加速结构绑定实例大小信息);
//
//	auto* m_顶层暂存缓冲区 = f_buf_create板载缓存(
//		ctx,
//		E_板载缓存类型::e_SSBO,
//		E_板载缓存类型::e_SSBO,
//		1,
//		m_加速结构绑定实例大小信息.accelerationStructureSize
//	);
//	f_bm_resize(光追顶层加速结构, m_加速结构绑定实例大小信息.accelerationStructureSize);
//
//
//	m_加速结构绑定几何实例信息.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
//	m_加速结构绑定几何实例信息.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
//	m_加速结构绑定几何实例信息.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
//	m_加速结构绑定几何实例信息.dstAccelerationStructure = (VkAccelerationStructureKHR)f_buf_get加速结构(光追顶层加速结构);
//	m_加速结构绑定几何实例信息.scratchData.deviceAddress = f_buf_getAddress(static_cast<S_VkArray缓存*>(m_顶层暂存缓冲区));
//
//
//	VkAccelerationStructureBuildRangeInfoKHR 实例区间;
//	实例区间.primitiveCount = num;
//	实例区间.primitiveOffset = 0;
//	实例区间.firstVertex = 0;
//	实例区间.transformOffset = 0;
//	const VkAccelerationStructureBuildRangeInfoKHR* 绑定偏移信息 = &实例区间;
//
//
//	f_Draw_Begin(&ctx, S_光追后端::m_加速结构创建命令缓存, S_光追后端::m_渲染Fence);
//	绘图配置->vkCmdBuildAccelerationStructures((VkCommandBuffer)S_光追后端::m_加速结构创建命令缓存, 1, &m_加速结构绑定几何实例信息, &绑定偏移信息);
//	f_Draw_end(&ctx, S_光追后端::m_加速结构创建命令缓存, S_光追后端::m_渲染Fence, 3);
//}

//void f_ob_构建顶层光追加速结构(S_物体* ob, uint32& offset) {
//	switch (ob->m_Type) {
//		case E_物体类型::t_多边形:
//		case E_物体类型::t_网格物体: {
//			
//			S_Mesh* me = f_ob_fromMesh(ob, E_物体网格元素类型::e_MT_光照);
//
//			uint32 实例数量 = ob->m_变换矩阵.m_Mem.m_数量;
//			if (me->m_索引->m_Mem.m_数量) {
//				auto* mat = f_buf_Mat44_ptr(ob->m_变换矩阵);
//
//				static uint8 空实例材质 = 0;
//				uint8* 实例材质 = &空实例材质;
//				bool 使用实例材质;
//				if (ob->m_实例材质ID.size() >= 实例数量) {
//					实例材质 = ob->m_实例材质ID.data();
//					使用实例材质 = true;
//				}
//				else {
//					使用实例材质 = false;
//				}
//
//				if (m_顶层实例加速结构->m_Size < 预分配) {
//					f_buf_resize(m_顶层实例加速结构, 预分配);
//				}
//				m_光追后端->f_预分配实例变换(实例数量);
//				for (int64 i = 0; i < 实例数量; ++i) {
//					if (m_光追后端->f_更新实例变换(
//						*me->m_底层光追加速结构
//						, f_mat3x4_转换(mat[i])
//						, offset + i
//						, me->m_光追网格ID
//						, 使用实例材质 ? 实例材质[i] : 0
//						, 0xff
//						, 实例数量
//					)) {
//					}
//				}
//				offset += 实例数量;
//			}
//			
//			break;
//		}
//
//		default:
//			break;
//	}
//
//	for (auto& ob : ob->m_子物体) {
//		f_ob_构建顶层光追加速结构(static_cast<S_物体*>(ob), offset);
//	}
//}








//static Mat44f f_ob_更新子骨骼IK(S_物体* 骨骼, S_骨骼IK* IK) {
//	Mat44f 当前骨骼矩阵 = f_mat44_构建XYZ变换矩阵(骨骼->m_变换);
//
//	if (骨骼->m_父物体) {
//		if (骨骼->m_父物体 == IK->m_始端) {
//
//		}
//		else {
//			Mat44f 父骨骼矩阵 = f_ob_更新子骨骼IK(骨骼->m_父物体, IK);
//
//			当前骨骼矩阵 = 父骨骼矩阵 * 当前骨骼矩阵;
//		}
//	}
//
//	当前骨骼矩阵;
//	return 当前骨骼矩阵;
//}


/*std::vector<C_Mat44> S_物体::f_get矩阵(uint32 ID) {
	if (m_变换矩阵.m_Mem.m_大小) {
		std::vector<C_Mat44> mat(m_变换矩阵->m_Size);

		m_变换矩阵->f_map();
		for (uint32 i = 0; i < m_变换矩阵->m_Size; ++i) {
			*((Mat44f*)mat[i].columns) = *((Mat44f*)(m_变换矩阵->m_mappedPtr));
		}
		m_变换矩阵->f_unmap();

		return mat;
	}

	C_Mat44 mat = C_Mat44::kIdentity;
	auto rx = f_构建旋转矩阵(m_变换.rotation.x, E_轴向::e_X);
	auto ry = f_构建旋转矩阵(m_变换.rotation.y, E_轴向::e_Y);
	auto rz = f_构建旋转矩阵(m_变换.rotation.z, E_轴向::e_Z);
	auto s = f_构建缩放矩阵(m_变换.scale);

	mat *= f_构建移动矩阵(m_变换.location);
	//mat *= r;
	mat *= rz;
	mat *= ry;
	mat *= rx;

	mat *= s;
	return { mat };
}*/

/*if (m_是否实例) {
	f_buf_Mat44_at(m_父物体->m_变换矩阵, m_变换ID) = *mat;
	//f_copy板载缓存array((S_板载缓存*)(m_父物体->m_变换矩阵), m_实例ID, mat, 1);
}
else {
	f_copy板载缓存array((S_板载缓存*)(m_变换矩阵), m_实例ID, mat, 1);
}*/
/*if (m_是否实例) {
	f_copy板载缓存array((S_板载缓存*)(m_父物体->m_变换矩阵), m_实例ID, mat, 1);
}
else {
	f_copy板载缓存array((S_板载缓存*)(m_变换矩阵), m_实例ID, mat, 1);
}*/


//Mat44f f_ob_get父对象变换矩阵(S_物体* Obj, uint32 ID, uint32 depth, bool 包含顶层) {
//	if (Obj->m_父物体) {
//		++depth;
//
//		switch (Obj->m_父物体->m_Type) {
//		case E_物体类型::t_骨骼:
//		
//		case E_物体类型::t_虚拟体:
//		case E_物体类型::t_点光源:
//		case E_物体类型::t_聚光灯:
//		case E_物体类型::t_区域光_圆形:
//		case E_物体类型::t_区域光_方形:
//		case E_物体类型::t_实例:
//			return f_ob_get父对象变换矩阵(Obj->m_父物体, ID, depth);
//
//		//case E_物体数据::t_物体包:
//		case E_物体类型::t_骨架:
//			if (!ID) return f_ob_get父对象变换矩阵(Obj->m_父物体, ID, depth);
//			return f_ob_get实例变换矩阵(Obj->m_父物体, ID);
//			break;
//		default:
//			break;
//		}
//
//
//		if (Obj->m_父物体->m_变换矩阵.m_Mem.m_大小) {
//			return f_ob_get父对象变换矩阵(Obj->m_父物体, ID, depth);
//		}
//
//
//		return f_ob_get实例变换矩阵(Obj->m_父物体, ID);
//	}
//
//	if (depth || 包含顶层) {
//		return f_ob_get实例变换矩阵(Obj, Obj->m_实例ID);
//	}
//
//	return f_mat44_identity();
//}


//vec4 f_ob_计算IK旋转向量(S_骨骼IK* IK) {
//	vec3 vs = {};
//	vec3 ve = {};
//	if (IK->m_始端) vs = f_ob_计算骨骼IK点(IK->m_始端, false);
//	if (IK->m_末端) ve = f_ob_计算骨骼IK点(IK->m_末端, true);
//
//	vec3 原末端控制向量 = (ve - vs);
//	vec3 中点坐标 = vs + 原末端控制向量 * 0.5f;
//	
//	原末端控制向量 = vec_normalize(原末端控制向量);
//	
//	vec3 IK控制点到中点向量 = vec_normalize(*IK->m_末端坐标 - 中点坐标);
//	vec3 旋转向量 = vec_normalize(vec_cross(原末端控制向量, IK控制点到中点向量));
//	return { 旋转向量.x, 旋转向量.y, 旋转向量.z , float32(-f_graph_两向量夹角弧度180(原末端控制向量, IK控制点到中点向量)) };
//	return f_graph_从轴向角度计算四元数(旋转向量, f_graph_两向量夹角弧度180(原末端控制向量, IK控制点到中点向量));
//}

//vec4 f_ob_计算IK旋转向量(S_骨架* 骨架, S_骨骼IK* IK, vec3& 原控制向量, float32& 原控制点距离, float32& 新控制点距离) {
//	auto mat_ptr = f_buf_Mat44_ptr(骨架->m_变换姿态);
//	S_骨骼* 骨骼 = f_ob_from骨骼(IK->m_末端);
//
//	vec3 vs = mat_ptr[IK->m_始端->m_实例ID] * vec3{};
//	vec3 ve = mat_ptr[IK->m_末端->m_实例ID] * vec3{ 0, 0, 骨骼->m_长度 };
//
//
//	//vec3 vs = f_ob_计算骨骼IK点(IK->m_始端, false);
//	//vec3 ve = f_ob_计算骨骼IK点(IK->m_末端, true);
//	原控制向量 = (ve - vs);
//	vec3 中点坐标 = vs + 原控制向量 * 0.5f;
//
//	原控制点距离 = vec_normalize(&原控制向量);
//
//	vec3 IK控制点到中点向量 = *IK->m_末端坐标 - 中点坐标;
//	新控制点距离 = vec_normalize(&IK控制点到中点向量);
//	vec3 旋转向量 = vec_normalize(vec_cross(原控制向量, IK控制点到中点向量));
//	return { 旋转向量.x, 旋转向量.y, 旋转向量.z , float32(-f_graph_两向量夹角弧度180(原控制向量, IK控制点到中点向量)) };
//}

//void f_ob_解算IK骨骼IK步进坐标(S_骨骼IK* ik, vec3* 骨节, const Mat44f* 骨骼变换矩阵, const float32* 骨骼长度, const Mat44f& 父级变换) {
//	//auto mat = f_mat44_Inverse(父级变换);
//	S_物体* ob = ik->m_末端;
//	vec3 末点坐标 = *ik->m_末端坐标;
//
//	for (;;) {
//		S_骨骼* 骨骼 = f_ob_from骨骼(ob);
//
//		uint32 offset = ob->m_实例ID;
//
//		vec3 s = 骨骼变换矩阵[offset] * vec3{ 0, 0, 0 };
//		vec3 新变更向量 = (末点坐标 - s);
//		vec_normalize(&新变更向量);
//
//		骨节[offset] = 父级变换 * 末点坐标;
//
//		末点坐标 = 末点坐标 - 新变更向量 * 骨骼长度[offset];
//
//		if (!(ob->m_父物体) || ob == ik->m_始端) {
//			break;
//		}
//		ob = ob->m_父物体;
//	}
//}


//void f_ob_更新骨骼IK(S_物体* ob, S_骨架* 骨架, Mat44f* 骨骼物体变换矩阵, const Mat44f& 父级变换) {
//	if(!骨架->m_骨头数量 || !骨架->m_IK数量) return;
//
//	float32* 骨骼长度 = f_buf_F32_ptr(骨架->m_骨骼长度);
//	auto 姿态变换_ptr = f_buf_Mat44_ptr(骨架->m_骨骼变换);
//
//	uint32 num = 骨架->m_骨骼变换.m_Mem.m_大小;
//	auto mat = f_mat44_Inverse(父级变换);
//	std::vector<vec3> 骨节坐标(num);
//	for (auto& e : ob->m_子物体) {
//		f_ob_ge骨节坐标(e, 骨节坐标.data(), 姿态变换_ptr, 骨骼长度, mat);
//	}
//
//	std::vector<Mat44f> tempMat(num);
//	memcpy(tempMat.data(), 姿态变换_ptr, sizeof(Mat44f) * tempMat.size());
//
//	for (uint32 i = 0; i < 骨架->m_IK数量; ++i) {
//		S_骨骼IK* ik = 骨架->m_IK[i];
//		
//		if (ik && ik->m_始端 && ik->m_末端) {
//			for (uint32 k = 0; k < 12; ++k) {
//				f_ob_解算IK骨骼IK步进坐标(ik, 骨节坐标.data(), tempMat.data(), 骨骼长度, mat);
//
//				for (auto& e : ob->m_子物体) {
//					f_ob_从骨节更新编辑骨骼(e, 骨节坐标.data(), 骨骼长度, tempMat.data(), { 0,0,0,1 }, 父级变换, e->m_变换.location, 0);
//				}
//			}
//		}
//		memcpy(骨骼物体变换矩阵, tempMat.data(), sizeof(Mat44f) * tempMat.size());
//	}
//}

//void f_ob_解算IK骨骼(S_骨骼IK* ik, Mat44f* 骨骼物体变换矩阵, const Mat44f* 骨骼变换矩阵, const float32* 骨骼长度, const Mat44f& 父级变换) {
//	std::vector<S_物体*> 骨骼物体链;
//	std::vector<float32> 骨骼偏移比例;
//
//	S_物体* ob = ik->m_末端;
//	vec3 末点坐标 = *ik->m_末端坐标;
//	std::vector<vec3> 修正旋转;
//	std::vector<float32> 旋转角度;
//	//Mat44f 父变换 = 骨骼物体变换矩阵[ik->m_始端->m_实例ID];
//	for (;;) {
//		骨骼物体链.push_back(ob);
//		S_骨骼* 骨骼 = f_ob_from骨骼(ob);
//
//		uint32 offset = ob->m_实例ID;
//		Mat44f 变换 = 骨骼变换矩阵[offset];
//
//		vec3 s = 变换 * vec3{ 0, 0, 0 };
//		vec3 e = 变换 * vec3{ 0, 0, 骨骼长度[offset] };
//
//		vec3 骨骼朝向 = e - s;
//		vec3 新变更向量 = 末点坐标 - s;
//		//vec3 新变更向量 = e - s;
//		vec_normalize(&新变更向量);
//		vec_normalize(&骨骼朝向);
//		
//		末点坐标 = 末点坐标 - 新变更向量 * 骨骼长度[offset];
//
//		旋转角度.push_back(f_graph_两向量夹角弧度180(新变更向量, 骨骼朝向));
//		//修正旋转.push_back(vec_cross(新变更向量, 骨骼朝向));
//		修正旋转.push_back(新变更向量);
//
//		
//		if (!(ob->m_父物体) || ob == ik->m_始端) {
//			break;
//		}
//		ob = ob->m_父物体;
//	}
//
//
//	float32 起始端骨骼长度;
//	Mat44f 父变换;
//	if (ik->m_始端->m_实例ID) {
//		父变换 = 骨骼变换矩阵[ik->m_始端->m_父物体->m_实例ID];
//		起始端骨骼长度 = 骨骼长度[ik->m_始端->m_父物体->m_实例ID];
//	} else {
//		父变换 = 父级变换;
//		起始端骨骼长度 = 0;
//	}
//
//	uint32 num = 骨骼物体链.size();
//	//auto rotMat = f_mat44_to_33(父变换);
//	vec3 l = { 0,0, 起始端骨骼长度 };
//	vec3 global_offset = (骨骼变换矩阵[ik->m_始端->m_实例ID] * f_mat44_构建移动矩阵(l) * vec3{ 0, 0, 0 });
//	
//	auto 偏移 = f_mat44_构建移动矩阵(global_offset);
//	
//	vec3 root骨骼反向 = 父变换 * vec3{0, 0, 0};
//	root骨骼反向 = vec_normalize(骨骼变换矩阵[ik->m_始端->m_实例ID] * vec3{ 0, 0, 0 } - root骨骼反向);
//	
//	vec4 父骨骼旋转 = f_graph_quatNormalize(f_graph_quat两向量(root骨骼反向, DEF_骨骼朝向));
//	for (int32 k = num; k > 0; ) {
//		--k;
//		uint32 offset = 骨骼物体链[k]->m_实例ID;
//
//		auto 骨骼方向 = f_graph_quat变换坐标(f_graph_quat反向(父骨骼旋转), 修正旋转[k]);
//		vec_normalize(&骨骼方向);
//
//		auto 当前旋转四元数 = f_graph_quat两向量(骨骼方向, DEF_骨骼朝向);
//		auto rot = f_graph_四元数转欧拉角(当前旋转四元数);
//
//		auto 变换 = 骨骼物体链[k]->m_变换;
//		变换.rotation = vec3{ -rot.x, -rot.y, rot.z };
//
//		骨骼物体变换矩阵[offset] = 父变换 * f_mat44_构建XYZ变换矩阵(变换);
//		父变换 = 骨骼物体变换矩阵[offset];
//
//		父骨骼旋转 = f_graph_quatNormalize(f_graph_quat相乘(当前旋转四元数, 父骨骼旋转));
//	}
//}




	//if (!ob->m_骨架) return;
	//
	//auto mat_ptr = f_buf_Mat44_ptr(ob->m_骨架->m_变换姿态);
	//
	//loc = DEF_骨骼朝向;
	//loc *= f_buf_F32_at(ob->m_骨架->m_骨骼长度, ob->m_实例ID);
	//
	//mat = f_mat44_构建XYZ变换矩阵({ loc, rot, {1,1,1} });
	//if (父级变换) {
	//	mat = (*父级变换) * mat;
	//}
	//mat_ptr[ob->m_实例ID] = mat;
	//
	//mat_ptr[ob->m_实例ID + ob->m_骨架->m_骨头数量].m00 = scale.x;
	//mat_ptr[ob->m_实例ID + ob->m_骨架->m_骨头数量].m01 = scale.y;
	//mat_ptr[ob->m_实例ID + ob->m_骨架->m_骨头数量].m02 = scale.z;
	//
	//return;
	//
	//vec3 骨骼端点 = mat * vec3{ 0, 0, 0 };
	//vec3 骨骼端点E = mat * vec3{ 0, 0, 1 };
	////起点 = (*父级变换) * 起点;
	//vec3 原_骨骼方向 = vec_normalize2(骨骼端点E - 骨骼端点);
	//
	//
	//Mat44f mat后半段变换矩阵重新赋值 = f_mat44_identity();
	//mat后半段变换矩阵重新赋值.m00 = scale.x;
	//mat后半段变换矩阵重新赋值.m01 = scale.y;
	//mat后半段变换矩阵重新赋值.m02 = scale.z;
	//
	//
	//
	////auto mat_ptr = f_buf_map板载缓存<Mat44f>(ob->m_骨架->m_姿态变换);
	////引用蒙皮传入GPU中的变换
	//if (ob->m_位置) {
	//	loc = f_an_曲线值(ob->m_位置, 0);
	//}
	//rot = ob->m_变换.rotation;
	//if (ob->m_旋转) {
	//	rot = f_an_曲线值(ob->m_旋转, 0);
	//}
	//scale = ob->m_变换.scale;
	//if (ob->m_缩放) {
	//	scale = f_an_曲线值(ob->m_缩放, 0);
	//}
	//mat = f_mat44_构建XYZ变换矩阵({ loc, rot , scale });
	//
	//
	//
	//vec3 初始端点 = {};
	//vec3 骨骼端点B = {};
	//
	//if (ob->m_父物体 && ob->m_父物体->m_Type == E_物体类型::t_骨骼) {
	//	auto 父变换 = mat_ptr[ob->m_父物体->m_实例ID];
	//	mat = 父变换 * mat;
	//
	//	auto mat_s = mat_ptr[ob->m_父物体->m_实例ID + ob->m_骨架->m_骨头数量];
	//	scale.x = mat_s.m00;
	//	scale.y = mat_s.m01;
	//	scale.z = mat_s.m02;
	//	//父Q.w = q.m13;
	//}
	//else {
	//	if (父级变换) mat = (*父级变换) * mat;
	//}
	//mat_ptr[ob->m_实例ID] = mat;
	//初始端点 = mat * vec3{ 0, 0, 0 };
	//骨骼端点B = mat * vec3{ 0, 0, 1 };
	//vec3 现姿态_骨骼方向 = vec_normalize2(骨骼端点B - 初始端点);
	//
	//
	//float32 弧度AB = f_graph_两向量夹角弧度180(原_骨骼方向, 现姿态_骨骼方向);
	//vec3 normal = vec_normalize2(vec_cross(原_骨骼方向, 现姿态_骨骼方向));
	//auto quat = QuatFromAxisAngle({ normal.x, normal.y, normal.z }, 弧度AB);
	//if (vec_len(normal) < 0.0000001) {
	//	quat = { 0,0,0,1 };
	//}
	//mat后半段变换矩阵重新赋值.m00 *= scale.x;
	//mat后半段变换矩阵重新赋值.m01 *= scale.y;
	//mat后半段变换矩阵重新赋值.m02 *= scale.z;
	//
	//
	//mat后半段变换矩阵重新赋值.m10 = quat.x;
	//mat后半段变换矩阵重新赋值.m11 = quat.y;
	//mat后半段变换矩阵重新赋值.m12 = quat.z;
	//mat后半段变换矩阵重新赋值.m13 = quat.w;
	//
	//mat后半段变换矩阵重新赋值.m20 = 骨骼端点.x;
	//mat后半段变换矩阵重新赋值.m21 = 骨骼端点.y;
	//mat后半段变换矩阵重新赋值.m22 = 骨骼端点.z;
	//
	//mat后半段变换矩阵重新赋值.m30 = 初始端点.x;
	//mat后半段变换矩阵重新赋值.m31 = 初始端点.y;
	//mat后半段变换矩阵重新赋值.m32 = 初始端点.z;
	//mat_ptr[ob->m_实例ID + ob->m_骨架->m_骨头数量] = (mat后半段变换矩阵重新赋值);


			//if (me->m_显示 && me->m_GPU参数布局.m_绑定数量) {
			//	if (me->m_多维材质数量) {
			//		f_ob_绘制元素(ob, me, 绘制元素, 渲染参数);
			//	}
			//	else 
			//	{
			//		me->m_Material->mf_GPU参数配置(me->m_Material, ob, me, 绘制元素);
			//
			//		if (me->m_顶点->m_Mem.m_数量) {
			//			//f_mesh_构建网格属性参数(me, DEF_ObType_Mesh);
			//			f_buf_网格引用_at(*me->m_网格属性, 0).m_Location = me->m_包围盒->pos;
			//		}
			//		else {
			//			S_ObMesh mesh = {
			//					0,
			//					0,
			//					0,
			//					0,
			//					0,
			//
			//					0,
			//					0,
			//					0,
			//					0,
			//
			//					DEF_ObType_Mesh,
			//					0,
			//					0,
			//					//{},
			//			};
			//			//f_buf_网格引用_at(*me->m_网格属性, 0) = mesh;
			//		}
			//
			//		if (me->m_绘制内存属性) {
			//			const S_GPU内存块* 物体参数[2] = { &ob->m_变换矩阵, &ob->m_实例颜色[绘制元素] };
			//			me->mf_绘制参数设置(me, 物体参数);
			//
			//			if (ob->m_骨架) ((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->BonePoseOffset = ob->m_骨架->m_姿态.m_Mem.m_偏移;
			//		}
			//
			//		if (me->m_参数槽.m_参数数量) {
			//			me->m_参数槽.m_参数槽[0] = 渲染参数.m_视图投影矩阵;
			//			me->m_参数槽.m_参数类型[0] = E_板载缓存类型::e_UBO;
			//			me->m_参数槽.m_绑定位置[0] = 0;
			//			me->m_参数槽.m_绑定数量[0] = 1;
			//
			//			me->m_参数槽.m_参数槽[1] = &ob->m_变换矩阵;
			//			me->m_参数槽.m_参数类型[1] = E_板载缓存类型::e_SSBO;
			//			me->m_参数槽.m_绑定位置[1] = 1;
			//			me->m_参数槽.m_绑定数量[1] = 1;
			//
			//			me->m_参数槽.m_纹理槽 = &S_全局缓存::g_全局模型纹理槽;
			//
			//			f_df_upGPU参数(me->m_Ctx.m_逻辑设备.设备, me->m_Material->m_着色线管->m_GPU参数set, me->m_参数槽);
			//		}
			//		else {
			//			assert(me->m_GPU参数布局.m_绑定数量 > 0);
			//
			//			me->m_GPU参数布局.m_参数槽[0] = 渲染参数.m_视图投影矩阵;
			//			me->m_GPU参数布局.m_绑定位置[0] = 0;
			//			me->m_GPU参数布局.m_参数槽[1] = ob->g_变换矩阵;
			//			me->m_GPU参数布局.m_绑定位置[1] = 1;
			//
			//			f_setGPU参数布局(me->m_Material, me->m_GPU参数布局);
			//		}
			//
			//
			//
			//		渲染参数.m_线宽 = me->m_线宽;
			//		渲染参数.m_实例数量 = ob->m_变换矩阵.m_Mem.m_数量;
			//		渲染参数.m_实例偏移 = 0;
			//
			//		渲染参数.m_索引内存偏移 = me->m_索引->m_Mem.m_偏移;
			//		渲染参数.m_索引内存数量 = me->m_索引->m_Mem.m_数量;
			//
			//
			//		if (me->m_间接 && me->m_间接->m_Mem.m_数量) {
			//			f_buf_Indirect_ptr(*me->m_间接)->firstInstance = 0;
			//		}
			//
			//		me->f_绘制(渲染参数);
			//	}
			//}







			//void f_ob_阴影绘制元素(S_物体* ob, S_Mesh* me, uint32 绘制元素, S_渲染参数& 渲染参数, bool 多维子元素) {
			//	uint32 obType = f_ob_getObType(ob);
			//
			//	for (uint32 i = 0; i < me->m_多维材质数量; ++i) {
			//		f_mesh_构建网格属性参数(ob, me, obType);
			//		//f_buf_网格引用_at(*me->m_网格属性, 0).m_Location = me->m_包围盒->pos;
			//
			//		if (me->m_元素->m_多维元素数量 > 0 && 多维子元素) {
			//			uint32 fo = me->m_多维材质槽[i].m_区间槽索引;
			//
			//			渲染参数.m_索引内存偏移 = me->m_元素->m_元素区间[fo].x + me->m_索引->m_Mem.m_偏移;
			//			渲染参数.m_索引内存数量 = me->m_元素->m_元素区间[fo].y;
			//			assert(渲染参数.m_索引内存偏移 + 渲染参数.m_索引内存数量 <= me->m_索引->m_Buf->m_Size);
			//		}
			//		else {
			//			渲染参数.m_索引内存偏移 = me->m_索引->m_Mem.m_偏移;
			//			渲染参数.m_索引内存数量 = me->m_索引->m_Mem.m_数量;
			//		}
			//
			//		assert(me->m_绘制内存属性);
			//		if (me->m_绘制内存属性) {
			//			const S_GPU内存块* 物体参数[2] = { &ob->m_变换矩阵, &ob->m_实例颜色[绘制元素] };
			//			me->mf_绘制参数设置(me, 物体参数, 多维子元素 ? i : 0);
			//
			//			if (ob->m_骨架) ((S_Vert_MeshDrawProp*)me->m_绘制内存属性)->BonePoseOffset = ob->m_骨架->m_姿态.m_Mem.m_偏移;
			//		}
			//
			//
			//
			//		me->m_多维材质槽[i].m_Material->mf_GPU参数配置(me->m_多维材质槽[i].m_Material, ob, me, 绘制元素, i);
			//
			//		me->m_多维材质槽[i].m_参数槽.m_参数槽[0] = 渲染参数.m_视图投影矩阵;
			//		me->m_多维材质槽[i].m_参数槽.m_参数类型[0] = E_板载缓存类型::e_UBO;
			//		me->m_多维材质槽[i].m_参数槽.m_绑定位置[0] = 0;
			//		me->m_多维材质槽[i].m_参数槽.m_绑定数量[0] = 1;
			//
			//		me->m_多维材质槽[i].m_参数槽.m_参数槽[1] = &(ob->m_变换矩阵);
			//		me->m_多维材质槽[i].m_参数槽.m_参数类型[1] = E_板载缓存类型::e_SSBO;
			//		me->m_多维材质槽[i].m_参数槽.m_绑定位置[1] = 1;
			//		me->m_多维材质槽[i].m_参数槽.m_绑定数量[1] = 1;
			//
			//		f_df_upGPU参数(me->m_Ctx.m_逻辑设备.设备, me->m_多维材质槽[i].m_Material->m_着色线管->m_GPU参数set, me->m_多维材质槽[i].m_参数槽);
			//
			//
			//
			//		渲染参数.m_线宽 = me->m_线宽;
			//		渲染参数.m_实例数量 = ob->m_变换矩阵.m_Mem.m_数量;
			//		渲染参数.m_实例偏移 = 0;
			//
			//
			//		if (me->m_间接 && me->m_间接->m_Mem.m_数量) {
			//			f_buf_Indirect_ptr(*me->m_间接)->firstInstance = 0;
			//		}
			//		渲染参数.m_间接 = me->m_间接;
			//
			//		me->f_绘制(渲染参数, i);
			//	}
			//}

void C_物体缓存列队数据::f_更新属性() {
	auto& 面 = f_ob_get数据(m_物体, 0);
	auto& 框 = f_ob_get数据(m_物体, 3);

	m_物体->m_Bound = f_mesh_计算包围盒(面.m_Mesh, nullptr);
	auto boundSize = m_物体->m_Bound.max - m_物体->m_Bound.min;
	f_me_fill顶点(框.m_Mesh, {S_VNTC{m_物体->m_Bound.min + boundSize*0.5f, boundSize,{}}});

	m_物体->m_isUpdate = true;
}

void f_ob_添加更新缓存列队(std::unique_ptr<C_物体缓存列队数据>&& data) {
	g物体列队缓存.push_back(std::move(data));
}

void f_ob_更新缓存列队() {
	if(g物体列队缓存.empty()) return;

	for (auto& e : g物体列队缓存) {
		e->f_更新属性();
	}
	g物体列队缓存.clear();
}




